Tenzro Labs
Tutorial 05 · Model API · Platform API

Run an agent on its own key

An approved agent calls models with its own API key. Its spend counts against the limits you approved, and only you can change them.
Step 01

Create the agent's API key

An agent calls models with a Platform API key that identifies it. Create one on the agent's page under Agents (API keys for this agent, then Create key), with POST /agents/{id}/keys, or with the create_agent_key MCP tool. Your own key needs manage.

shell
curl https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT/keys \
  -H "Authorization: Bearer $TENZRO_MANAGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "research-bot prod"}'
response
{
  "id": "key_Zb81Qm0sP4aT",
  "name": "research-bot prod",
  "prefix": "tzl_3kQ9aZ1x",
  "permissions": ["inference"],
  "agent_id": "agt_Zp3kQ9x1RmW4sT",
  "created_at": "2026-09-26T08:00:00.000Z",
  "last_used_at": null,
  "revoked_at": null,
  "secret": "tzl_…"
}
tool call · create_agent_key
{
  "agent_id": "agt_Zp3kQ9x1RmW4sT",
  "name": "research-bot prod"
}
  • The key has the inference permission only. The secret is returned once; keep it where the agent runs.
  • Only an active agent can be given keys. For one still waiting for approval, the call is refused with 409 agent_not_active.
  • Usage is billed to your credit and counted against the agent's approved limits, separately from yours.
Step 02

Call models with it

The agent uses the same model API and endpoints as any other caller, exactly as in tutorial 01. Only the key changes.

shell
export TENZRO_API_KEY="tzl_..."   # the agent's key
python · agent.py
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.tenzro.xyz/v1", api_key=os.environ["TENZRO_API_KEY"])

reply = client.chat.completions.create(
    model="qwen3.5-4b",
    messages=[
        {"role": "system", "content": "You are research-bot. Answer briefly."},
        {"role": "user", "content": "Summarise what an embedding is."},
    ],
)
print(reply.choices[0].message.content)
javascript · agent.mjs
import OpenAI from "openai";

const client = new OpenAI({ baseURL: "https://api.tenzro.xyz/v1", apiKey: process.env.TENZRO_API_KEY });

const vectors = await client.embeddings.create({
  model: "qwen3-embedding-0.6b",
  input: ["first passage", "second passage"],
});
console.log(vectors.data.length);
Step 03

Stay within the approved limits

Every limit comes from the settings the owner approved with their passkey; a proposal that is still waiting is never enforced. Within them the agent works with no further prompts. Beyond them, the request is refused before any work is done:

402 agent_daily_limit
daily_limit_credits
The agent has spent this many credits today (UTC). Refused for the rest of the day.
402 agent_total_limit
total_limit_credits
The agent has spent this many credits in total.
403 agent_expired
expires_in_days
The delegation has ended.
403 agent_inactive
status
The agent is not active.
response · 402
{
  "error": {
    "message": "This agent's key may not make requests now (agent daily limit).",
    "type": "insufficient_quota",
    "code": "agent_daily_limit"
  }
}

Payments are capped on the Tenzro Network itself by max_transaction_tnzo and max_daily_tnzo. When the network refuses something outside the agent's scope, the refusal is returned as it is, never as partial success.

Handle a refusal in the agent

python
from openai import APIStatusError

try:
    reply = client.chat.completions.create(
        model="qwen3.5-4b",
        messages=[{"role": "user", "content": "Next task"}],
    )
except APIStatusError as e:
    if e.code in ("agent_daily_limit", "agent_total_limit", "agent_expired", "agent_inactive"):
        # Stop and report: retrying will not succeed until the owner approves new limits.
        print("Refused:", e.code)
    else:
        raise
Step 04

Watch what it spends

GET /agents/{id} and the get_agent MCP tool include spend.today_credits and spend.total_credits next to its approved limits. The agent's page shows the same under Platform spend.

shell
curl -s https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT \
  -H "Authorization: Bearer $TENZRO_READ_KEY" | jq '{status, limits, spend}'
response
{
  "status": "active",
  "limits": {
    "max_transaction_tnzo": null,
    "max_daily_tnzo": null,
    "daily_limit_credits": 20000,
    "total_limit_credits": 500000,
    "expires_in_days": 90
  },
  "spend": { "today_credits": 0, "total_credits": 0 }
}
Step 05

Raise a limit

The agent cannot raise its own limits, and neither can the Platform. Propose new settings with POST /agents/{id}/settings or update_agent; the owner approves them with their passkey on https://accounts.tenzro.xyz. Nothing changes until then, and the agent keeps working under its current limits.

shell
curl https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT/settings \
  -H "Authorization: Bearer $TENZRO_MANAGE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"daily_limit_credits": 50000}'
# returns { "approve_url": "https://accounts.tenzro.xyz/agents/approve/apr_…", "agent": { … } }
Step 06

Revoke a key or the agent

Revoke one key to rotate it; that takes effect at once. Revoking the agent is a proposal the owner approves with their passkey.

Revoke one key
DELETE /keys/{id}
revoke_api_key(key_id)
Propose revoking the agent
POST /agents/{id}/revoke
revoke_agent(agent_id)
shell
# One key
curl -X DELETE https://platform.tenzro.xyz/api/keys/key_Zb81Qm0sP4aT -H "Authorization: Bearer $TENZRO_MANAGE_KEY"

# The agent: returns an approve_url for the owner
curl -X POST https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT/revoke -H "Authorization: Bearer $TENZRO_MANAGE_KEY"
Once the owner approves, the agent's identity is revoked on the Tenzro Network and every key and token it holds stops working. Create a new agent to replace it.