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.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.
Under the Hood: why is it structured this way?
Under the Hood: why is it structured this way?
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.