Use your coding agent
Your coding agent (Claude Code, Cursor, or anything that reads URLs) can integrate m8tes for you. Paste an example prompt; it pulls the full docs corpus and writes the integration against your codebase. This page is about your agent doing the integration work, not the agents m8tes hosts.
Example prompt
Copy this into your coding agent. Swap the "What I want" block for your feature, keep the docs links and ground rules:
You are integrating the m8tes hosted agent SDK into this repo.
m8tes runs agents as API resources (Python SDK, TypeScript SDK, React embed, REST).
I write the prompt and pick the tools; m8tes runs the sandbox, memory, scheduling,
approvals, and billing.
Docs (read these first — prefer the corpus, then the stack page you need):
- Full docs corpus: https://www.m8tes.ai/llms-full.txt
- Quick start (Python / TypeScript / React·Next.js): https://www.m8tes.ai/docs/quickstart
- Embed a UI (React / Next.js MateChat): https://www.m8tes.ai/docs/embed-a-ui
- Multi-tenancy (user_id): https://www.m8tes.ai/docs/users
- API reference: https://www.m8tes.ai/docs/api-reference
- Errors: https://www.m8tes.ai/docs/api-errors
- Custom tools / MCP: https://www.m8tes.ai/docs/custom-tools
Ground rules:
- Base URL: https://api.m8tes.ai/api/v2 (the /api/v2 prefix is required).
- Auth: M8TES_API_KEY env var (m8_…). Never hardcode the key or paste it into chat.
- Stack (pick what this repo uses):
- Python: pip install -U "m8tes>=4.49.0" → from m8tes import M8tes
- TypeScript/Node: npm i @m8tes/sdk → import { M8tes } from "@m8tes/sdk"
- React/Next.js UI: npm i @m8tes/react → server route with createM8tesHandler,
client MateChat inside M8tesProvider (see Embed a UI)
- Every run belongs to a task. List a task's runs with
client.runs.list(task_id=..., user_id="customer_123") (Python) or the TS equivalent.
- After a run, gate on run.error_code before trusting run.output.
- Multi-tenant product embeds: pass user_id on agents/runs/memories so each end user
is isolated. Keep strict mode on for customer-facing apps.
- Agents that talk to my end users should use prompt_profile="bare" so they do not
brand as m8tes.
What I want built (example — replace with my real feature):
A CRM assistant inside our product. Each logged-in user gets an isolated agent
(user_id = our customer id). They can ask "what's blocking Acme's renewal?", the
agent uses HubSpot + Gmail when connected, streams the reply into our existing
chat UI, and pauses for approval before sending outbound email.Credentials
Set the API key as an environment variable. Never paste it into a prompt or commit it:
export M8TES_API_KEY=m8_your_key_hereCreate or rotate a key with POST /api/v2/token or from the Developer dashboard.
No account yet?
Create one in Python; the key comes back immediately:
from getpass import getpass
import m8tes
result = m8tes.signup("you@example.com", getpass("Choose a password: "), "yourname")
print(result.api_key) # export as M8TES_API_KEYOr let the agent sign you up (passwordless HTTP flow)
POST /api/v2/signup needs no auth. Omit password and the agent stays credential-free:
curl -X POST https://api.m8tes.ai/api/v2/signup \
-H "Content-Type: application/json" \
-d '{"email": "alex@acme.com", "first_name": "alex"}'The response contains a setup-only API key. The activation link is emailed to the person only; it is never in the API response. From there:
- Connect a model provider (local) or use the $1 test lane / top up (prod embeds), then set up. For a cold hello-world, use the API starter credit on the pinned test model (see Quick start). For personal development, connect a matching model subscription and run without
user_id. For production embeds, top up after the starter pin for the full catalog. Then use the key as a Bearer token to create agents and start runs. Unverified accounts may complete up to 25 runs before email verification is required. - Detect the gate. After that verification threshold, runs return
403witherror.details.error_code == "EMAIL_VERIFICATION_REQUIRED". Tell the person to open the activation email; resend it withPOST /api/v2/verify/resend. - Hand off. The person clicks the link, sets a password, and activates. At activation the setup-only key is revoked. The person mints their own key from the Developer dashboard or
POST /api/v2/token. - Know when. Poll
GET /api/v2/verify/statuswith the setup key:is_verifiedflips totrue. A401also means the hand-off happened (the key was revoked).
product picks what to provision: "api" (default, the developer product) or "platform" (the team product, with Lead mate and Day-1 onboarding). "api" accounts start in strict multi-tenant mode; pass "require_end_user_id": false at signup for personal development only. This setting persists account-wide. For customer-facing apps, keep strict mode on and pass user_id.
Run an agent with none of our branding
An agent you embed in your product should sound like your product. By default an agent knows it runs on m8tes: it calls itself a mate, can describe what m8tes does, and knows our pricing. That is right for a team using m8tes directly and wrong for an agent your customers talk to.
Set prompt_profile to "bare" and none of that reaches the agent:
agent = client.agents.create(
name="Acme Support",
instructions="You are Acme Support. Answer billing questions for Acme customers.",
prompt_profile="bare",
user_id="cust_42",
)bare removes branding, not ability. Permissions, approvals, memory, files, integrations
and your own Agent Skills all work exactly the same.
Switch an existing agent any time with client.agents.update(id, prompt_profile="bare");
it takes effect on that agent's next run.
Turn off any built-in tool
Every agent gets built-in tools (memory, task history, issue reporter, owner-notify email, desktop). Some are wrong for embeds: report_issue files feedback with us, and notify emails the account owner, not your end user. Name them in disabled_builtin_tools to unmount:
agent = client.agents.create(
name="Acme Support",
prompt_profile="bare",
disabled_builtin_tools=["feedback", "notify", "computer_use"],
user_id="cust_42",
)Valid names: GET /api/v2/built-in-tools. Pass teammate_id to see what a run will actually mount after your disable list. Unknown names are rejected, so a typo cannot leave a tool on.
for t in client.built_in_tools.list(agent_id=agent.id).data:
print(t.name, t.enabled)See exactly what we inject
Returns the real prompt the agent will run, rendered by the same code that runs it:
sp = client.agents.system_prompt(agent.id, user_id="cust_42")
print(sp.prompt_profile, sp.characters)
assert "m8tes" not in sp.system_prompt.replace("/home/daytona/m8tes-files/", "")One deliberate exception: /home/daytona/m8tes-files/ is the real sandbox directory your
agent writes to when it shares a file, so that path survives in bare. It is a filesystem
path the agent uses, never something it is told to say.
Per-run context (memories, documents, connected tools, the triggering channel) is resolved when a run starts and is not included in this response.
Why the hand-off is secure:
The blocked-run response:
{
"error": {
"type": "permission_error",
"code": 403,
"message": "Verify your email to keep running. Check your inbox for the activation link (resend: POST /api/v2/verify/resend).",
"request_id": "req_...",
"doc_url": "https://www.m8tes.ai/docs/api-errors#error-types",
"details": {
"error_code": "EMAIL_VERIFICATION_REQUIRED",
"runs_used": 25,
"verification_threshold": 25,
"runs_remaining": 50,
"balance_micros": 0,
"balance_usd": "0.0000",
"topup_url": "/billing/api"
}
}
}runs_used counts every run the account made, on any meter: it is the preview trip-wire, not a billing figure. The two allowances below it are separate meters and neither pays for the other.
balance_micros/balance_usd: the prepaid wallet (runs withuser_id). Appears only on accounts with a prepaid balance.runs_remaining: the platform plan (your own first-party runs: web app, and API calls with nouser_id).
A user_id run debits the balance and leaves runs_remaining untouched. On a new API account (strict multi-tenant by default), you will see runs_remaining sitting at the full plan allowance. See Billing & usage.
Good first asks
- "add a per-user CRM assistant with HubSpot, stream replies into our Next.js chat UI"
- "wire @m8tes/sdk so each customer_id maps to user_id and approvals pause outbound email"
- "subscribe a webhook to run.completed and run.failed, and verify signatures"
Verify the integration
- Run the generated quickstart end to end. Confirm provider sign-in finishes and the run returns output.
- Check
run.error_codeis empty on success paths, and that failures surface the code. - Confirm end-user isolation: a resource created with one
user_idis invisible to another.
Next: Quick start · Errors · Webhook events