> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Identity and Delegation

> Set up agent identities with On-Behalf-Of delegation to control what agents can do on behalf of users.

<Info>
  **Coming Soon** — Agent Identity and OBO Delegation is under active development and will be available in an upcoming release. This page describes the planned behavior and configuration.
</Info>

As AI agents evolve from simple assistants to autonomous actors, enterprise security demands a fundamental shift: agents must have their own identity. Without it, an agent either impersonates the user (losing accountability) or uses a shared service account (losing user context). Agent Identity in TrueFoundry solves this by making agents first-class participants in the authorization chain — with their own identity, their own permissions, and their own audit trail.

## The Problem: Invisible Agents

Today, when an agent calls an MCP server or a downstream API, the system sees either the user or a service account — never the agent itself. This creates blind spots:

| Scenario                            | What the downstream system sees                 | What's missing                           |
| ----------------------------------- | ----------------------------------------------- | ---------------------------------------- |
| Agent uses user's token directly    | The user                                        | Which agent acted? Was it authorized to? |
| Agent uses a shared service account | A service identity                              | Which user's data is being accessed?     |
| Agent impersonates the user         | The user (indistinguishable from direct access) | The agent's role in the decision chain   |

In each case, the audit trail is incomplete, authorization is coarse-grained, and policy enforcement cannot distinguish between a human clicking a button and an autonomous agent deciding to take action.

***

## Agent Spec with Identity

When you create or register an agent in Agent Hub, the `identity` field defines how the agent establishes its identity in the delegation chain. The identity determines how a (user, agent) pair is established for authorization and audit.

### Full Agent Spec

```yaml theme={"dark"}
name: <string>                    # Unique agent name within the organization
description: <string>             # Human-readable description
source: <string>                  # Prompt reference (for Agent Hub agents)
type: <agent_hub | byoa>          # Agent type

# Identity configuration
identity:
  type: <managed_credentials | federated_token | virtual_account>
  # ... type-specific fields (see below)

# MCP servers the agent can access
mcp_servers:
  - <mcp-server-name>

# Access control
collaborators:
  - subject: <user:email | team:name>
    role_id: <agent-manager | agent-user>
```

TrueFoundry supports three identity modes:

| Mode                    | How agent identity is established                                                  | Who performs OBO exchange   |
| ----------------------- | ---------------------------------------------------------------------------------- | --------------------------- |
| **Managed Credentials** | Agent is registered in external IdP; TrueFoundry stores the credentials            | TrueFoundry                 |
| **Federated Token**     | Agent performs its own OBO exchange externally                                     | The agent                   |
| **Virtual Account**     | Agent is identified by a TrueFoundry Virtual Account; user token passed separately | No external exchange needed |

***

## Identity Mode 1: Managed Credentials

In this mode, the organization registers the agent as an OAuth application in their IdP (Okta, Azure AD) and provides the agent's client credentials to TrueFoundry. When a user interacts with the agent, TrueFoundry performs the OBO token exchange using these credentials — producing a token with `sub=user` and `act=agent`.

### When to Use

* Agent Hub agents where TrueFoundry runs the agent
* You want TrueFoundry to handle the full OBO lifecycle (exchange, caching, refresh)
* The downstream MCP server needs a standard OBO token from your IdP

### Spec

```yaml theme={"dark"}
name: finance-assistant
description: AI agent for financial analysis and reporting
source: prompts/finance-analysis-v3
type: agent_hub

identity:
  type: managed_credentials
  idp_type: okta
  client_id: ${TFY_SECRET:finance-agent-client-id}
  client_secret: ${TFY_SECRET:finance-agent-client-secret}
  token_endpoint: https://your-org.okta.com/oauth2/default/v1/token
  allowed_scopes:
    - api:access:read
    - api:access:write

mcp_servers:
  - order-analytics-mcp
  - financial-reports-mcp

collaborators:
  - subject: user:finance-team@example.com
    role_id: agent-user
```

### Identity Fields — Managed Credentials

| Field                     | Required | Description                                                                                |
| ------------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `identity.type`           | Yes      | Set to `managed_credentials`                                                               |
| `identity.idp_type`       | Yes      | Identity provider type: `okta` or `azure_ad`                                               |
| `identity.client_id`      | Yes      | The agent's OAuth client ID, registered in your IdP                                        |
| `identity.client_secret`  | Yes      | The agent's OAuth client secret (use TrueFoundry Secrets)                                  |
| `identity.token_endpoint` | Yes      | The IdP's token endpoint URL for token exchange                                            |
| `identity.allowed_scopes` | No       | Maximum scopes this agent can request. If omitted, the IdP's policy determines the scopes. |

### How It Works

```mermaid theme={"dark"}
sequenceDiagram
    participant User
    participant IdP as Identity Provider
    participant Agent as Agent Hub Agent
    participant TFY as TrueFoundry Platform
    participant MCP as MCP Server

    rect rgb(240, 248, 255)
        Note over User, IdP: 1. User Authentication
        User->>IdP: Authenticate (SSO)
        IdP-->>User: User Token (T₀)
    end

    rect rgb(245, 255, 245)
        Note over User, Agent: 2. User Interacts with Agent
        User->>Agent: Request + T₀
        Agent->>TFY: Forward to platform
    end

    rect rgb(255, 245, 238)
        Note over TFY, IdP: 3. TrueFoundry Performs OBO Exchange
        TFY->>IdP: Token Exchange<br/>subject_token=T₀<br/>client_id=agent's client_id<br/>client_secret=agent's secret
        Note over IdP: Validate user token<br/>Verify agent is authorized<br/>Scope intersection
        IdP-->>TFY: OBO Token<br/>sub=user, act=agent
    end

    rect rgb(245, 245, 255)
        Note over TFY, MCP: 4. Call MCP Server with OBO Token
        TFY->>MCP: Tool invocation + OBO Token
        Note over MCP: Validate token<br/>See sub=user, act=agent<br/>Enforce authorization
        MCP-->>TFY: Response
        TFY-->>Agent: Response
        Agent-->>User: Result
    end
```

<Steps>
  <Step title="User authenticates via SSO">
    The user signs in through the organization's IdP and obtains a user token (T₀).
  </Step>

  <Step title="User interacts with the agent">
    The user sends a request through Agent Hub (UI or API). The agent receives the user's token.
  </Step>

  <Step title="TrueFoundry performs OBO exchange">
    TrueFoundry uses the **agent's stored client credentials** to perform an [RFC 8693](https://www.rfc-editor.org/rfc/rfc8693.html) token exchange with the IdP. The user's token is the `subject_token`. The IdP validates the user, verifies that this agent (`client_id`) is authorized to act on behalf of users, and issues an OBO token with:

    * `sub` = the user
    * `act` = the agent
    * `scp` = intersection of user's and agent's permissions
  </Step>

  <Step title="OBO token is used for downstream calls">
    TrueFoundry uses the OBO token when the agent invokes MCP server tools. The downstream MCP server sees both the user and the agent in the token and can enforce its own authorization.
  </Step>
</Steps>

**The OBO token produced:**

```json theme={"dark"}
{
  "sub": "user@example.com",
  "aud": "com.api.analytics",
  "iss": "https://your-org.okta.com/oauth2/default",
  "scp": ["api:access:read", "api:access:write"],
  "act": {
    "sub": "finance-assistant-client-id"
  },
  "exp": 1675291144,
  "iat": 1675287544
}
```

The downstream MCP server sees `sub=user@example.com` (whose data is being accessed) and `act.sub=finance-assistant-client-id` (which agent is acting).

<Tip>
  TrueFoundry caches OBO tokens keyed by (user, agent, scopes) and refreshes them automatically. The IdP is called only when a token is missing or near expiry.
</Tip>

### IdP Setup

<Tabs>
  <Tab title="Okta">
    <Steps>
      <Step title="Create a Service App for the agent">
        1. In the Okta Admin Console, go to **Applications > Applications**
        2. Click **Create App Integration** and select **API Services**
        3. Name the app with the agent's name (e.g., `Finance Assistant Agent`)
        4. In **General Settings**, click **Edit** and enable **Token Exchange** under Grant Types
        5. Copy the **Client ID** and **Client Secret**
      </Step>

      <Step title="Create custom scopes">
        1. Go to **Security > API** and select your authorization server
        2. Under **Scopes**, add the scopes the agent needs (e.g., `api:access:read`, `api:access:write`)
      </Step>

      <Step title="Create an access policy and rule">
        1. Under **Access Policies**, create a policy assigned to the agent's service app
        2. Add a rule permitting the `token_exchange` grant type with the required scopes
      </Step>

      <Step title="Configure the agent in TrueFoundry">
        Add the Client ID, Client Secret, and token endpoint to the agent's `identity` configuration. Store credentials as TrueFoundry Secrets.
      </Step>
    </Steps>
  </Tab>

  <Tab title="Azure AD (Entra ID)">
    <Steps>
      <Step title="Register an app for the agent">
        1. In the Azure Portal, go to **Microsoft Entra ID > App registrations**
        2. Click **New registration** and name the app (e.g., `Finance Assistant Agent`)
        3. Under **Certificates & secrets**, create a client secret
        4. Under **API permissions**, add the delegated permissions the agent needs
      </Step>

      <Step title="Enable OBO permissions">
        1. On the MCP server's app registration, go to **Expose an API**
        2. Add the agent's app as an authorized client application
        3. Grant admin consent
      </Step>

      <Step title="Configure the agent in TrueFoundry">
        Add the Client ID, Client Secret, and token endpoint (`https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token`) to the agent's `identity` configuration.
      </Step>
    </Steps>
  </Tab>
</Tabs>

***

## Identity Mode 2: Federated Token

In this mode, the agent performs its own OBO token exchange externally — outside of TrueFoundry — and calls Agent Hub directly with the resulting OBO token. TrueFoundry validates the token, extracts the user identity (`sub`) and agent identity (`act`), and uses them for authorization and audit.

### When to Use

* BYOA / A2A agents that run outside TrueFoundry
* The agent already integrates with the IdP and manages its own tokens
* You want the agent to control the OBO exchange lifecycle
* Multi-platform agents that call TrueFoundry as one of several backends

### Spec

```yaml theme={"dark"}
name: external-trading-bot
description: Third-party trading analysis agent
type: byoa

identity:
  type: federated_token
  idp_type: okta
  jwks_uri: https://your-org.okta.com/oauth2/default/v1/keys
  issuer: https://your-org.okta.com/oauth2/default
  audience: external-trading-bot-app
  agent_claim: act.sub

mcp_servers:
  - trading-api-mcp
  - market-data-mcp

collaborators:
  - subject: user:trading-desk@example.com
    role_id: agent-user
```

### Identity Fields — Federated Token

| Field                  | Required | Description                                                                  |
| ---------------------- | -------- | ---------------------------------------------------------------------------- |
| `identity.type`        | Yes      | Set to `federated_token`                                                     |
| `identity.idp_type`    | Yes      | Identity provider type: `okta` or `azure_ad`                                 |
| `identity.jwks_uri`    | Yes      | The IdP's JWKS endpoint for token signature validation                       |
| `identity.issuer`      | Yes      | Expected `iss` claim in the OBO token                                        |
| `identity.audience`    | No       | Expected `aud` claim. If set, tokens with a different audience are rejected. |
| `identity.agent_claim` | No       | JSON path to the agent identifier in the token. Defaults to `act.sub`.       |

### How It Works

```mermaid theme={"dark"}
sequenceDiagram
    participant User
    participant IdP as Identity Provider
    participant Agent as External Agent
    participant TFY as TrueFoundry<br/>(Agent Hub / Gateway)
    participant MCP as MCP Server

    rect rgb(240, 248, 255)
        Note over User, IdP: 1. User Authentication
        User->>IdP: Authenticate (SSO)
        IdP-->>User: User Token (T₀)
    end

    rect rgb(245, 255, 245)
        Note over Agent, IdP: 2. Agent Performs OBO Exchange
        User->>Agent: Interact + T₀
        Agent->>IdP: Token Exchange<br/>subject_token=T₀<br/>client_id=agent's own credentials
        IdP-->>Agent: OBO Token<br/>sub=user, act=agent
    end

    rect rgb(255, 245, 238)
        Note over Agent, TFY: 3. Agent Calls Agent Hub with OBO Token
        Agent->>TFY: Request + OBO Token
        Note over TFY: Validate token signature (JWKS)<br/>Check issuer, audience<br/>Extract sub=user, act=agent<br/>Match agent identity to registry<br/>RBAC + policy check
    end

    rect rgb(245, 245, 255)
        Note over TFY, MCP: 4. Forward to MCP Server
        TFY->>MCP: Tool invocation + OBO Token
        Note over MCP: Validate token<br/>See sub=user, act=agent
        MCP-->>TFY: Response
        TFY-->>Agent: Response
        Agent-->>User: Result
    end
```

<Steps>
  <Step title="User authenticates via SSO">
    The user signs in through the organization's IdP and obtains a user token (T₀).
  </Step>

  <Step title="Agent performs its own OBO exchange">
    The external agent uses its own IdP-registered client credentials to exchange the user's token for an OBO token. This exchange happens **outside TrueFoundry** — the agent manages the IdP interaction directly. The resulting OBO token has `sub=user` and `act=agent`.
  </Step>

  <Step title="Agent calls Agent Hub with the OBO token">
    The agent sends requests to TrueFoundry's Agent Hub API (or the MCP Gateway) with the OBO token in the `Authorization` header. TrueFoundry validates the token:

    * Signature verification using the configured `jwks_uri`
    * `iss` matches the configured `issuer`
    * `aud` matches the configured `audience` (if set)
    * `act` claim is present — extracts the agent identity
    * Matches the agent identity to a registered agent in TrueFoundry
  </Step>

  <Step title="Authorization and forwarding">
    TrueFoundry evaluates RBAC and Cedar policies using the extracted user and agent identities. If authorized, the OBO token is forwarded to the downstream MCP server.
  </Step>
</Steps>

### Agent Code (Federated Token)

```python theme={"dark"}
import httpx
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

def get_obo_token(user_token: str) -> str:
    """Exchange user token for an OBO token using the agent's own credentials."""
    response = httpx.post(
        "https://your-org.okta.com/oauth2/default/v1/token",
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
            "subject_token": user_token,
            "subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
            "client_id": AGENT_CLIENT_ID,
            "client_secret": AGENT_CLIENT_SECRET,
            "scope": "api:access:read api:access:write",
            "audience": "external-trading-bot-app",
        },
    )
    return response.json()["access_token"]

obo_token = get_obo_token(user_sso_token)

transport = StreamableHttpTransport(
    url="{GATEWAY_BASE_URL}/mcp/trading-api-mcp/server",
    headers={"Authorization": f"Bearer {obo_token}"}
)

async with Client(transport) as client:
    result = await client.call_tool("get_positions", {"account": "A-100"})
```

***

## Identity Mode 3: Virtual Account

In this mode, the agent is identified by a TrueFoundry [Virtual Account](/docs/ai-gateway/mcp/mcp-gateway-auth-security#virtual-account-token) — no external IdP registration required for the agent. The caller passes two tokens: the **Virtual Account token** (which identifies the agent and has access to it) and the **user's SSO token** (which identifies the end user). TrueFoundry combines them to establish the (user, agent) pair.

### When to Use

* You don't want to register agents in an external IdP
* The downstream MCP servers don't require IdP-issued OBO tokens — they trust TrueFoundry's authentication
* BYOA agents that call Agent Hub as an API backend
* Quick setup without IdP integration complexity

### Spec

```yaml theme={"dark"}
name: customer-support-agent
description: Customer support agent with per-user context
type: byoa

identity:
  type: virtual_account
  virtual_account_id: customer-support-va

mcp_servers:
  - ticketing-mcp
  - knowledge-base-mcp

collaborators:
  - subject: user:support-team@example.com
    role_id: agent-user
```

### Identity Fields — Virtual Account

| Field                         | Required | Description                                                                  |
| ----------------------------- | -------- | ---------------------------------------------------------------------------- |
| `identity.type`               | Yes      | Set to `virtual_account`                                                     |
| `identity.virtual_account_id` | Yes      | The name/ID of the Virtual Account in TrueFoundry that represents this agent |

### How It Works

```mermaid theme={"dark"}
sequenceDiagram
    participant User
    participant IdP as Identity Provider
    participant Agent as External Agent
    participant TFY as TrueFoundry<br/>(Agent Hub / Gateway)
    participant MCP as MCP Server

    rect rgb(240, 248, 255)
        Note over User, IdP: 1. User Authentication
        User->>IdP: Authenticate (SSO)
        IdP-->>User: User Token
    end

    rect rgb(245, 255, 245)
        Note over User, Agent: 2. User Interacts with Agent
        User->>Agent: Request + User Token
    end

    rect rgb(255, 245, 238)
        Note over Agent, TFY: 3. Agent Calls Agent Hub with Both Tokens
        Agent->>TFY: Request<br/>Authorization: VA Token<br/>X-TFY-User-Token: User Token
        Note over TFY: Validate VA token<br/>→ identifies agent<br/>Validate User token (SSO/IdP)<br/>→ identifies user<br/>Establish (user, agent) pair<br/>RBAC + policy check
    end

    rect rgb(245, 245, 255)
        Note over TFY, MCP: 4. Forward to MCP Server
        TFY->>MCP: Tool invocation + user context
        MCP-->>TFY: Response
        TFY-->>Agent: Response
        Agent-->>User: Result
    end
```

<Steps>
  <Step title="User authenticates via SSO">
    The user signs in through the organization's IdP and obtains a user token.
  </Step>

  <Step title="User interacts with the agent">
    The agent receives the user's token through your application's standard flow.
  </Step>

  <Step title="Agent calls Agent Hub with both tokens">
    The agent sends the request with two tokens:

    * `Authorization: Bearer <virtual-account-token>` — authenticates the agent to TrueFoundry and identifies which agent is calling
    * `X-TFY-User-Token: <user-sso-token>` — provides the end user's identity

    TrueFoundry validates the VA token (identifying the agent), validates the user token against the configured SSO/IdP, and establishes the (user, agent) pair.
  </Step>

  <Step title="Authorization and forwarding">
    TrueFoundry evaluates RBAC (is the user allowed? is the agent allowed? is the tool allowed?) and Cedar policies. If authorized, the request is forwarded to the MCP server with the user's context.
  </Step>
</Steps>

### Setup

<Steps>
  <Step title="Create a Virtual Account">
    1. Navigate to **Settings > Virtual Accounts** in the TrueFoundry UI
    2. Click **Create Virtual Account**
    3. Name it after the agent (e.g., `customer-support-va`)
    4. Add permissions for the MCP servers the agent needs to access
  </Step>

  <Step title="Register the agent with the Virtual Account">
    Create the agent in Agent Hub and set `identity.virtual_account_id` to the Virtual Account you created.
  </Step>

  <Step title="Configure user token validation">
    Ensure your organization has [Identity Providers](/docs/platform/identity-providers) configured so TrueFoundry can validate the user's SSO token and extract the user's identity.
  </Step>
</Steps>

### Agent Code (Virtual Account)

```python theme={"dark"}
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport

VA_TOKEN = "your-virtual-account-token"

transport = StreamableHttpTransport(
    url="{GATEWAY_BASE_URL}/mcp/ticketing-mcp/server",
    headers={
        "Authorization": f"Bearer {VA_TOKEN}",
        "X-TFY-User-Token": user_sso_token,
    }
)

async with Client(transport) as client:
    result = await client.call_tool(
        "get_tickets",
        {"status": "open", "assigned_to": "me"}
    )
    print(result)
```

TrueFoundry resolves the Virtual Account → agent identity (`customer-support-agent`), validates the user token → user identity (`user@example.com`), and evaluates authorization using the (user, agent) pair.

<Note>
  With the Virtual Account mode, the downstream MCP server receives the user's context through TrueFoundry's standard outbound authentication — not via an IdP-issued OBO token. If the MCP server requires a standard RFC 8693 OBO token with `sub` and `act` claims, use **Managed Credentials** or **Federated Token** instead.
</Note>

***

## Comparing Identity Modes

|                                       | Managed Credentials                     | Federated Token                 | Virtual Account                |
| ------------------------------------- | --------------------------------------- | ------------------------------- | ------------------------------ |
| **Who performs OBO exchange**         | TrueFoundry                             | The agent                       | No exchange needed             |
| **Agent registered in external IdP**  | Yes                                     | Yes                             | No                             |
| **Agent credentials stored in**       | TrueFoundry Secrets                     | Agent's infrastructure          | TrueFoundry (VA token)         |
| **IdP round-trip for agent identity** | Yes (at TrueFoundry)                    | Yes (at agent)                  | No                             |
| **Downstream token format**           | RFC 8693 OBO token                      | RFC 8693 OBO token              | TrueFoundry-managed            |
| **Best for**                          | Agent Hub agents needing IdP OBO tokens | BYOA agents managing own tokens | Quick setup, no IdP complexity |
| **Agent developer effort**            | Zero (provide credentials)              | Implement token exchange        | Minimal (pass two tokens)      |
| **What TrueFoundry receives**         | User's SSO token                        | Pre-exchanged OBO token         | VA token + user token          |

***

## Agent Authorization: Collaborators + Policies

TrueFoundry extends the existing **collaborator model** to support agents as first-class principals. Just as you add users and teams as collaborators on an MCP server, you can add agents — with optional tool-level restrictions. This works identically across all three identity modes.

### Agents as Collaborators

In the MCP server's collaborator list, agents appear alongside users:

```yaml theme={"dark"}
name: payments-api-mcp
collaborators:
  - subject: user:finance-team@example.com
    role_id: mcp-server-user
  - subject: agent:finance-assistant
    role_id: mcp-server-user
    tools: ["process_refund", "get_transaction", "list_invoices"]
  - subject: agent:audit-bot
    role_id: mcp-server-viewer
    tools: ["list_invoices", "get_transaction"]
```

| Field     | Description                                                                           |
| --------- | ------------------------------------------------------------------------------------- |
| `subject` | `agent:<agent-name>` — the agent's identity from TrueFoundry's registry               |
| `role_id` | The access level (same roles as user collaborators)                                   |
| `tools`   | Optional tool-level restriction — if specified, the agent can only invoke these tools |

This means:

* `finance-assistant` can call `process_refund`, `get_transaction`, and `list_invoices`
* `audit-bot` can only call `list_invoices` and `get_transaction` (read-only audit)
* Neither agent can call tools not in their list, even if the underlying user has broader access

### Advanced Policies with Cedar

For organizations that need more sophisticated authorization — conditions based on user department, time-of-day, delegation chains, or environment — TrueFoundry supports [Cedar](https://www.cedarpolicy.com/) policies as an extension layer on top of the collaborator model.

Cedar policies are **optional**. The collaborator model handles most use cases. Cedar adds power when you need conditional logic.

<AccordionGroup>
  <Accordion title="When to use collaborator permissions vs Cedar policies">
    | Requirement                                                        | Use Collaborators | Use Cedar |
    | ------------------------------------------------------------------ | :---------------: | :-------: |
    | Agent X can access MCP server Y                                    |         ✓         |           |
    | Agent X can only use tools A, B, C                                 |         ✓         |           |
    | Agent X can access MCP server Y **only for users in Finance**      |                   |     ✓     |
    | No agent can access PII tools, ever                                |                   |     ✓     |
    | Agent X can only operate during business hours                     |                   |     ✓     |
    | Agent X can access MCP server Y **only when delegated by Agent Z** |                   |     ✓     |
  </Accordion>

  <Accordion title="Example: Block all agents from PII tools">
    ```cedar theme={"dark"}
    forbid(
      principal is Agent,
      action == Action::"call_tool",
      resource == McpServer::"hr-system"
    ) when {
      resource.tool in ["get_ssn", "get_salary", "get_personal_info"]
    };
    ```
  </Accordion>

  <Accordion title="Example: Allow agents only for specific user departments">
    ```cedar theme={"dark"}
    permit(
      principal in AgentGroup::"finance-agents",
      action == Action::"call_tool",
      resource == McpServer::"payments-api"
    ) when {
      context.user.department == "Finance" &&
      context.user.role in ["manager", "director"]
    };
    ```
  </Accordion>

  <Accordion title="Example: Time-bounded agent access">
    ```cedar theme={"dark"}
    permit(
      principal == Agent::"trading-agent",
      action == Action::"call_tool",
      resource == McpServer::"trading-api"
    ) when {
      context.time.hour >= 9 && context.time.hour < 17 &&
      context.time.day_of_week in ["Mon", "Tue", "Wed", "Thu", "Fri"]
    };
    ```
  </Accordion>

  <Accordion title="Example: Delegation chain constraints">
    ```cedar theme={"dark"}
    permit(
      principal == Agent::"data-agent",
      action == Action::"call_tool",
      resource == McpServer::"analytics-mcp"
    ) when {
      context.delegation_chain contains Agent::"research-agent"
    };
    ```

    This allows `data-agent` to access analytics **only** when it was invoked by `research-agent` as a sub-agent, not when acting independently.
  </Accordion>
</AccordionGroup>

***

## Authorization Evaluation Flow

When an agent makes a request, authorization is evaluated in layers — regardless of which identity mode is used:

```mermaid theme={"dark"}
flowchart TD
    A[Request arrives] --> B{Identity Mode?}
    B -->|Managed Credentials| C[TrueFoundry performs OBO exchange]
    B -->|Federated Token| D[Validate OBO token via JWKS]
    B -->|Virtual Account| V[Validate VA token + user token]
    C --> E[Extract user + agent identity]
    D --> E
    V --> E
    E --> F{RBAC: User is collaborator?}
    F -->|No| X[403 — User not authorized]
    F -->|Yes| G{RBAC: Agent is collaborator?}
    G -->|No| Y[403 — Agent not authorized]
    G -->|Yes| H{Tool allowed for agent?}
    H -->|No| Z[403 — Tool not in allowed list]
    H -->|Yes| I{Cedar Policies}
    I -->|No policies configured| J[Forward to MCP Server]
    I -->|PERMIT| J
    I -->|DENY| W[403 — Cedar policy denied]
```

<Steps>
  <Step title="Resolve identity">
    For **managed credentials**, TrueFoundry performs the OBO exchange and produces the token. For **federated tokens**, TrueFoundry validates the incoming OBO token against the configured JWKS. For **virtual accounts**, TrueFoundry validates the VA token and the user token separately. In all cases, the result is a validated (user, agent) pair.
  </Step>

  <Step title="RBAC — User access">
    Does the user (from `sub` or the user token) have collaborator access to this MCP server?
  </Step>

  <Step title="RBAC — Agent access">
    Is the agent (from `act` or the VA mapping) listed as a collaborator on this MCP server?
  </Step>

  <Step title="RBAC — Tool restriction">
    If the agent's collaborator entry specifies allowed tools, is the requested tool in the list?
  </Step>

  <Step title="Cedar policies (optional)">
    If Cedar policies are configured, evaluate them with the full context: agent identity, user claims, tool, time, delegation chain. A `forbid` always takes precedence over `permit`.
  </Step>

  <Step title="Forward to MCP server">
    The request is forwarded to the downstream MCP server with the appropriate authentication based on the MCP server's outbound auth configuration.
  </Step>
</Steps>

***

## Multi-Agent Delegation Chains

When agents orchestrate sub-agents, the OBO token carries the full delegation path via nested `act` claims. TrueFoundry tracks and enforces policies at every hop.

### Example: Parent Agent → Sub-Agent → MCP Server

```mermaid theme={"dark"}
sequenceDiagram
    participant User
    participant PA as Parent Agent<br/>(research-agent)
    participant SA as Sub-Agent<br/>(data-agent)
    participant TFY as TrueFoundry
    participant MCP as Analytics MCP

    User->>PA: "Analyze Q4 revenue trends"
    Note over PA: Holds OBO token<br/>sub=user, act=research-agent

    PA->>SA: Delegate data retrieval + OBO token
    Note over SA: Performs OBO exchange<br/>subject_token = parent's OBO token

    SA->>TFY: Query analytics + new OBO token
    Note over TFY: Validate token<br/>sub=user<br/>act={data-agent, act: research-agent}<br/>RBAC + Cedar check
    TFY->>MCP: Tool call + OBO token
    MCP-->>TFY: Data
    TFY-->>SA: Data
    SA-->>PA: Processed results
    PA-->>User: Analysis report
```

The OBO token carries the full chain:

```json theme={"dark"}
{
  "sub": "user@example.com",
  "act": {
    "sub": "data-agent-client-id",
    "act": {
      "sub": "research-agent-client-id"
    }
  }
}
```

The downstream MCP server sees the user, the immediate agent (`data-agent`), and the originating agent (`research-agent`). Cedar policies can reason about the full chain — for example, allowing `data-agent` to access analytics only when delegated by `research-agent`.

***

## Audit and Observability

Every agent action is logged with full identity attribution:

```json theme={"dark"}
{
  "timestamp": "2026-04-10T14:30:00Z",
  "user": "user@example.com",
  "agent": "finance-assistant",
  "identity_mode": "managed_credentials",
  "delegation_chain": ["finance-assistant"],
  "mcp_server": "payments-api",
  "tool": "process_refund",
  "rbac_decision": "PERMIT",
  "cedar_decision": "PERMIT",
  "matching_policy": "finance-agents-refund-policy",
  "scopes_used": ["api:access:write"],
  "status": "success"
}
```

This gives security teams the ability to:

* Trace every action back to both the user and the agent
* See which identity mode was used (`managed_credentials`, `federated_token`, or `virtual_account`)
* Identify which authorization layer (RBAC or Cedar) authorized or denied the action
* Detect anomalous agent behavior patterns
* Generate compliance reports showing agent-specific access patterns

***

## FAQ

<AccordionGroup>
  <Accordion title="Which identity mode should I choose?">
    | Situation                                              | Recommended Mode        |
    | ------------------------------------------------------ | ----------------------- |
    | Agent Hub agent, MCP server needs standard OBO token   | **Managed Credentials** |
    | External agent that already manages its own IdP tokens | **Federated Token**     |
    | Quick setup, MCP servers trust TrueFoundry auth        | **Virtual Account**     |
    | No IdP integration, just need user+agent attribution   | **Virtual Account**     |
  </Accordion>

  <Accordion title="Do I need to register the agent in my external IdP?">
    **Managed credentials** and **Federated token**: Yes — the agent must be registered as an OAuth application in your IdP.

    **Virtual account**: No — the agent is identified entirely within TrueFoundry using a Virtual Account. No external IdP registration needed.
  </Accordion>

  <Accordion title="Can I use multiple identity modes in the same organization?">
    Yes. Each agent independently configures its identity mode. You can have Agent Hub agents with managed credentials, BYOA agents with federated tokens, and other agents with virtual accounts — all in the same TrueFoundry deployment.
  </Accordion>

  <Accordion title="What if an agent doesn't need identity?">
    The `identity` field is optional. Agents without identity work exactly as they do today — using the user's token or a shared service account for downstream calls. Identity is only needed when you require agent attribution, per-agent authorization, or OBO delegation.
  </Accordion>

  <Accordion title="How does TrueFoundry match a federated token to a registered agent?">
    TrueFoundry extracts the agent identifier from the token using the configured `agent_claim` (default: `act.sub`). It matches this value against the registered agents in TrueFoundry's registry. If no matching agent is found, the request is rejected with a `403`.
  </Accordion>

  <Accordion title="Can agents act without a user context?">
    For autonomous agent scenarios (background tasks, scheduled jobs), agents can use their own client credentials (managed/federated modes) or just a VA token (virtual account mode) without a user token. Collaborator permissions and Cedar policies are evaluated based on the agent's identity alone. The agent's effective permissions are limited to what its own configuration allows — it cannot access user-specific resources.
  </Accordion>

  <Accordion title="What happens if the Virtual Account doesn't have access to the MCP server?">
    The request is denied with a `403`. The Virtual Account must be added as a collaborator on the MCP server (or the agent that maps to it must be). Both the user and the agent must have access for the request to succeed.
  </Accordion>
</AccordionGroup>
