Skip to main content
This page covers two separate things that are easy to conflate: an agent authenticating to T3N (proving who it is), and an agent being authorized to call a specific contract function (proving it’s allowed to).
This is about agents acting through your contract. If you’re looking for how you, the tenant developer, authenticate to manage your own deployment, see Set Up Development Environment instead — that’s a different session.

1. An agent authenticates like any other T3N session

An agent has its own identity — its own key pair and its own DID — separate from the tenant that owns the contract it’s calling. It authenticates the same way any T3N client does: handshake, then authenticate, then read its own DID back from the session. There’s nothing tenant-specific to configure here.
Never hard-code or derive an agent’s DID any more than you would a tenant’s — always read it back from the authenticated session, exactly as agentDid is read above. And generate AGENT_KEY as its own separate credential (the same way you’d generate any Ethereum-style keypair) — don’t reuse your tenant’s T3N_API_KEY for an agent.

2. Being authenticated is not being authorized

Authenticating proves the agent’s identity. It does not grant it permission to call anything. Before an agent can invoke a contract function — especially one that makes an outbound HTTP call — the user who owns the data (the “data owner,” not the agent, and not you as the tenant developer) has to explicitly grant that agent access:
userClient here is the data owner’s own authenticated session — built the same way as t3n/agentClient above, just with the user’s own key. See Invoke your contract for the full construction and where TENANT_SCRIPT/scriptVersion come from. A grant is scoped three ways at once: which contract, which functions on it, and which external hosts it may reach. An agent with no matching grant can still call the contract — the call just fails at the point it tries to reach the network, with host/http.egress_denied.
Splitting authentication from authorization means a compromised or misbehaving agent key doesn’t automatically mean compromised data access — the blast radius of a leaked agent key is exactly whatever scripts, functions, and hosts a user has explicitly granted it, nothing more. It also means a user can revoke an agent’s access without the agent’s key changing at all — they just stop re-issuing the grant.

Direct (self) calls work the same way

If a user is invoking their own contract directly rather than through a separate agent, the same grant mechanism applies — they just grant to their own DID (a self-grant) instead of an agent’s.

Full working example

See Invoke your contract for this in context, including the search/book contract call itself. For why the outbound call fails without a grant even when the contract code is correct, see Outbound HTTP calls are authorized by the user, not the contract.
Some SDK type definitions reference a broader delegation-credential API (functions for building and signing standalone delegation credentials, separate from the agent-auth-update grant shown above). That surface isn’t confirmed or documented yet — if you find it in the SDK’s TypeScript types and need it, ask in the developer Telegram rather than guessing at the signatures, and we’ll get this page updated once it’s verified.