Identity & agents
Every account has a Tenzro identity rooted in the person's passkeys. Agents act under that identity, delegated by the owner's passkey: the owner approves what each agent may do and spend, and only the owner can change or revoke it. Nothing is custodial.
Your identity
- Created when you sign up: one passkey (Face ID, Touch ID, Windows Hello or a security key) becomes your
did:tenzro:human:…identity and a passkey-controlled wallet on the Tenzro Network. - If that step fails or you skip it, your account still works; the Wallet page provisions it with one click. Retrying uses the same passkey, so it never creates a second identity.
- Add devices from the wallet page: a passkey you already hold approves the new one. Sending is enabled once a second device is linked, so losing one device cannot strand the wallet.
- Programmatically:
GET https://platform.tenzro.xyz/api/identityor theget_identityMCP tool.
Agents
An agent is an identity under yours, did:tenzro:machine:<your id>:<agent id>, with its own wallet. It is always delegated by your passkey. The Platform, an API key or an MCP client can propose an agent or a change to one; only you can approve it, with your passkey, on your Tenzro Labs account at https://accounts.tenzro.xyz.
| Step | Who | What happens |
|---|---|---|
| 1. Propose | You, your app or your agent | Name, capabilities, limits and an optional expiry. The Platform returns an approve_url. |
| 2. Approve | You, with your passkey | Open approve_url. Review the settings, adjust them if you like, and approve with your passkey. The Tenzro Network registers the agent under your identity. |
| 3. Active | The Platform | Coming back from the approval (or reading the agent) collects the result. The settings you approved are the ones that apply. |
| 4. Operate | The agent | Calls models with an API key you create for it. Usage is billed to your credit and counted against its approved limits. |
| 5. Change limits | You, with your passkey | Propose new settings; nothing changes until you approve them the same way. |
| 6. Revoke | You, with your passkey | Once approved, its identity is revoked on the network and every API key it holds stops. |
An agent runs on serving nodes of the Tenzro Network, spread across independent operators. The Platform picks them from the nodes that currently serve agents; while the network has none, creating an agent is refused with 409 no_serving_nodes.
Propose an agent
curl https://platform.tenzro.xyz/api/agents -H "Authorization: Bearer $TENZRO_MANAGE_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "research-bot",
"capabilities": ["inference"],
"daily_limit_credits": 20000,
"total_limit_credits": 500000,
"expires_in_days": 90
}'{
"approve_url": "https://accounts.tenzro.xyz/agents/approve/apr_3xQkV8mZp1LwRt2sN0cY",
"agent": {
"id": "agt_Zp3kQ9x1RmW4sT",
"name": "research-bot",
"status": "awaiting_approval",
"approval": { "kind": "create", "state": "pending", "approve_url": "https://accounts.tenzro.xyz/agents/approve/apr_3xQkV8mZp1LwRt2sN0cY" },
"limits": null,
"proposed": {
"agent_name": "research-bot",
"capabilities": ["inference"],
"max_transaction_tnzo": "",
"max_daily_tnzo": "",
"daily_limit_credits": 20000,
"total_limit_credits": 500000,
"expires_in_days": 90
},
"did": null,
"serving": { "nodes": 3, "operators": 2 }
}
}A passkey cannot be pressed from code, so give approve_url to the person who owns the account. The link is valid for 30 minutes. The create_agent MCP tool returns the same shape.
Approve
The approval page on your Tenzro Labs account shows the proposed settings and how many independent operators will serve the agent. You can change the capabilities, limits and expiry before approving. Your passkey signs exactly those terms, and the Tenzro Network registers the agent only against that signature. You are then sent back to the agent's page on the Platform.
Read the result
Reading the agent collects the outcome of an outstanding approval, so call it after the owner says they approved.
curl https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT -H "Authorization: Bearer $TENZRO_READ_KEY"{
"id": "agt_Zp3kQ9x1RmW4sT",
"name": "research-bot",
"status": "active",
"approval": null,
"capabilities": ["inference"],
"limits": {
"max_transaction_tnzo": null,
"max_daily_tnzo": null,
"daily_limit_credits": 10000,
"total_limit_credits": 500000,
"expires_in_days": 90
},
"did": "did:tenzro:machine:e0b27720-3043-84d5-9b66-49eba92b1a8d:7c1d…",
"wallet_address": "0x4b1f…",
"serving": { "nodes": 3, "operators": 2 },
"network_key_held": true,
"approved_at": "2026-09-26T09:12:00.000Z",
"expires_at": "2026-12-25T09:12:00.000Z",
"spend": { "today_credits": 0, "total_credits": 0 }
}Here the owner lowered the daily limit from 20,000 to 10,000 credits while approving: limits are always the approved values. The status of an agent is one of:
| status | Meaning |
|---|---|
awaiting_approval | Proposed; waiting for the owner at approval.approve_url. |
active | Registered on the network. approval is set while a change or revocation waits for the owner. |
failed | The network refused it. error carries the network's reason word for word. |
expired | The approval link expired before it was used. Start again from the Agents page. |
revoked | Revoked on the network; its API keys no longer work. |
Give it an API key
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"}'Active agents only. The key identifies the agent: every request it makes counts against the agent's approved limits. The secret is returned once.
Change limits
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}'{
"approve_url": "https://accounts.tenzro.xyz/agents/approve/apr_9LmQ2cVx7RtK0pWs4NaE",
"agent": { "id": "agt_Zp3kQ9x1RmW4sT", "status": "active",
"approval": { "kind": "update", "state": "pending", "approve_url": "…" },
"limits": { "daily_limit_credits": 10000, … } }
}Fields you leave out keep their approved values; the name cannot change. Until the owner approves, the agent keeps working under its current limits. Only one change can wait at a time. MCP: update_agent.
Revoke
curl -X POST https://platform.tenzro.xyz/api/agents/agt_Zp3kQ9x1RmW4sT/revoke -H "Authorization: Bearer $TENZRO_MANAGE_KEY"Returns { approve_url, agent } like a change. Once the owner approves with their passkey, the agent's identity is revoked on the Tenzro Network and every Platform API key it holds stops working. MCP: revoke_agent.
Limits and scope
| Setting | Enforced by | Effect |
|---|---|---|
daily_limit_credits | Tenzro Labs Platform | Requests are refused with 402 agent_daily_limit once the agent has spent this many credits today (UTC). |
total_limit_credits | Tenzro Labs Platform | Refused with 402 agent_total_limit once reached. |
max_transaction_tnzo | Tenzro Network | The most the agent can pay in any one payment. |
max_daily_tnzo | Tenzro Network | The most the agent can pay per day. |
expires_in_days | Both | The delegation ends; the Platform refuses its keys with 403 agent_expired. |
capabilities | Both | inference: call models. payments: also transfer and pay for services on the network. |
Every limit comes from the settings the owner approved; a proposal that is still waiting is never enforced. When the network refuses something outside an agent's scope, the refusal is returned as it is, never as partial success.
Behind the approval
The Platform talks to the account service server to server, authenticated as its own OAuth client. You never call these endpoints yourself; they are shown so you can see exactly what is proposed and what comes back.
POST https://accounts.tenzro.xyz/api/accounts/{sub}/agent-approvals
Authorization: Basic <platform client credentials>
Content-Type: application/json
{
"kind": "create",
"settings": {
"agent_name": "research-bot",
"capabilities": ["inference"],
"max_transaction_tnzo": "",
"max_daily_tnzo": "",
"daily_limit_credits": 20000,
"total_limit_credits": 500000,
"expires_in_days": 90
},
"serving_nodes": [
{ "machine_did": "did:tenzro:machine:…", "operator_did": "did:tenzro:…" },
{ "machine_did": "did:tenzro:machine:…", "operator_did": "did:tenzro:…" }
],
"return_to": "https://platform.tenzro.xyz/agents/agt_Zp3kQ9x1RmW4sT?collect=1"
}{ "id": "apr_3xQkV8mZp1LwRt2sN0cY", "approve_url": "https://accounts.tenzro.xyz/agents/approve/apr_3xQkV8mZp1LwRt2sN0cY" }A change sends "kind": "update" with the agent's agent_did, the proposed settings and its current serving nodes; a revocation sends "kind": "revoke" and agent_did only. The Platform then collects the outcome, once:
GET https://accounts.tenzro.xyz/api/accounts/{sub}/agent-approvals/apr_3xQkV8mZp1LwRt2sN0cY
Authorization: Basic <platform client credentials>{ "state": "pending" }
{ "state": "expired" }
{ "state": "failed", "error": "<the network's refusal, word for word>" }
{ "state": "collected", "agent_did": "did:tenzro:machine:…" }
{
"state": "approved",
"kind": "create",
"agent_did": "did:tenzro:machine:e0b27720-3043-84d5-9b66-49eba92b1a8d:7c1d…",
"network": {
"identity": { "did": "did:tenzro:machine:…", "controller_did": "did:tenzro:human:…" },
"wallet": { "address": "0x4b1f…" },
"serving_nodes": [{ "machine_did": "did:tenzro:machine:…", "operator_did": "did:tenzro:…", "dpop_jkt": "…" }],
"api_key": "<agent-scoped network key, returned once>"
},
"settings": {
"agent_name": "research-bot",
"capabilities": ["inference"],
"max_transaction_value": "",
"max_daily_spend": "",
"expires_in_days": 90,
"daily_limit_credits": 10000,
"total_limit_credits": 500000
}
}settingsare the ones the owner signed. They replace whatever the Platform proposed; TNZO caps come back in wei.- The answer is handed over once. A second read returns
collected, and the account service keeps no copy of the network key.