Skip to main content

Building tmates

Tmates are just Python packages with a manifest, a prompt brain, and a small amount of glue code. This guide walks through the entire lifecycle so your tmate behaves consistently across Tmates Cloud and self-hosted deployments.

1. Plan the role

Before touching code, write down:

  • Mission statement – one sentence describing what the tmate solves (e.g., “Turns raw meeting notes into structured action plans”).
  • Success signals – what a good response looks like (attachments, tone, metadata, etc.).
  • Required tools – APIs, files, or SDK integrations it needs.

This planning step becomes the foundation for the manifest and prompt instructions.

2. Scaffold the agent folder

Every tmate lives under app/agents/<key> with this structure:

app/agents/<key>/
├── manifest.yaml
├── agent.py
├── brain.py
├── interface/
│ └── api.py
├── tests/
└── prompts/
  • manifest.yaml describes branding, capabilities, environment variables, and tools.
  • agent.py exposes AGENT_CLASS inheriting from AgentBase.
  • brain.py (or another module) houses the core logic/prompt.
  • interface/api.py adapts CLI/API requests into the brain.
  • tests/ holds pytest suites for regression coverage.

Use an existing tmate (e.g., app/agents/adam) as a reference, but don’t copy prompts verbatim.

3. Write the manifest

Key sections:

  • name, slug, description, category – used in the catalog and clients.
  • branding – emoji/color/avatar so the UI can render a consistent face.
  • playbook.optional_params – documented knobs users can tweak.
  • tools – describe each callable capability (inputs, outputs, keywords for routing).
  • env.required / env.optional – document every secret or feature flag the tmate needs.

Keep the manifest honest: if a variable is required, mark it as such so self-hosted installs don’t miss it.

4. Implement the brain

In brain.py (or a similar module):

  • Import run_agent_api_request from app.sdk.agents.tmates_agents_sdk to handle sessions and attachments.
  • Implement run_prompt or equivalent function that calls OpenAI/Azure models, other services, or your custom tools.
  • Sanitize outputs (strip URLs you’re going to send as attachments, format Markdown, etc.).

Example skeleton:

from app.sdk.agents.tmates_agents_sdk import run_agent_api_request

async def run_prompt(message, user_id, session_id, context=None):
# Call LLMs, tools, or custom logic
return "Thanks for the update!"

def process_api_request(request, user_context=None):
return run_agent_api_request(
agent_key="planner",
author_name="Planner",
request=request,
user_context=user_context,
run_prompt=run_prompt,
)

5. Add tests

Use pytest to lock in behavior:

  • Mock the LLM/tool layer so tests run quickly.
  • Cover manifest changes (e.g., schema validation) if you add new sections.
  • Simulate CLI invocations with python run.py agent <key> --message "..." inside the test suite or a smoke-test script.

6. Run locally

WORKER_KEY=<key> python run.py agent <key> --message "first draft" --user-id <supabase_user_id>

This exercises the same code path that Celery workers use. Fix any issues before moving on.

7. Checklist before publishing

  • Manifest is complete (branding, tools, env vars, version).
  • Unit/integration tests pass.
  • CLI smoke test succeeds.
  • Generated files are registered via generated_media_registry if applicable.
  • Logging goes through app.logger.log or structured logging (no stray print).

Once you’re confident, head to Publishing tmates to package and distribute your creation.