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

# Outbound authentication

Outbound authentication solves credentials when the agent calls third-party services. Agent Identity encrypts and stores API keys and OAuth tokens, keeps them out of your code, with refresh behavior determined by the flow and provider configuration. Storing an API key does not automatically rotate that key in the third-party service. Choose a method by scenario:

| Method | Provider type | When to use |
| - | - | - |
| API key | API Key | Simple, fixed-credential service-to-service calls |
| OAuth2 M2M | OAuth Client | Service-to-service auth with token expiry and refresh |
| OAuth2 user federation | OAuth Client | The app acts on a user's behalf and needs their consent |

## Create an outbound credential

<Steps>
  <Step title="Activate Agent Identity">
    Open the [Agent Identity](https://console.volcengine.com/identity) activation page, accept the terms, and activate and authorize.
  </Step>

  <Step title="Create the credential">
    In the console, go to **Authentication › Outbound Credentials**, create an API Key or OAuth Client for your method, and fill in the credentials (API key, Client ID, Client Secret, callback URL, and so on).
  </Step>
</Steps>

## Use it in an agent

Once the credential exists, two wrappers inject it into the agent: `VeIdentityFunctionTool` for plain function tools and `VeIdentityMcpToolset` for MCP toolsets. Both take an `auth_config` — produced by the methods below — and Agent Identity injects the credential at runtime.

Configure the model and create the credential provider in Agent Identity first. The process needs permission to read that provider. Set `SERVICE_PROFILE_URL` to an HTTPS profile endpoint you control that accepts a Bearer API key. This example reads data without modifying external resources

```python title="app.py" lines theme={null}
import asyncio
import os
import httpx
from veadk import Agent
from veadk.integrations.ve_identity import VeIdentityFunctionTool, api_key_auth

async def get_profile(api_key: str) -> dict:
    """Read the current account profile."""
    async with httpx.AsyncClient(timeout=30) as client:
        response = await client.get(
            os.environ["SERVICE_PROFILE_URL"],
            headers={"Authorization": f"Bearer {api_key}"},
        )
        response.raise_for_status()
        return response.json()

tool = VeIdentityFunctionTool(
    func=get_profile,
    auth_config=api_key_auth(provider_name="my-api-provider"),
    into="api_key",
)
agent = Agent(name="profile_assistant", tools=[tool])
print(asyncio.run(agent.run("Read my account profile")))
```

## API key

The simplest method, for service-to-service calls with fixed credentials. In the console, **New › New API Key**, fill in a name, the third-party API key, and how it's passed (Header or Query). Build the `auth_config` with `api_key_auth`:

```python lines theme={null}
from veadk.integrations.ve_identity import api_key_auth

auth_config = api_key_auth(provider_name="my-api-provider")
```

## OAuth2 M2M

For service-to-service calls — using tokens with expiry and scopes. In the console, **New › New OAuth Client**, choose the **Machine to Machine (M2M)** flow; credentials can use a built-in provider (Lark, Coze, Google, GitHub), an OIDC issuer URL, or fully custom endpoints. Build the `auth_config` with `oauth2_auth` and `auth_flow="M2M"`:

```python lines theme={null}
from veadk.integrations.ve_identity import oauth2_auth

auth_config = oauth2_auth(
    provider_name="my-oauth2-m2m-provider",
    scopes=["api://your-service/.default"],
    auth_flow="M2M",
)
```

## OAuth2 user federation

For cases where the app accesses a third-party service on a user's behalf. In the console, **New › New OAuth Client**, choose the **User Federation (USER\_FEDERATION)** flow and set the callback URL. Build the `auth_config` with `oauth2_auth` and `auth_flow="USER_FEDERATION"`:

```python lines theme={null}
from veadk.integrations.ve_identity import oauth2_auth

auth_config = oauth2_auth(
    provider_name="github-oauth2-provider",
    scopes=["repo", "user"],
    auth_flow="USER_FEDERATION",
    callback_url="https://your-app.com/oauth/callback",
)
```

On first use, the user authorizes the app in the third-party service; Agent Identity runs the authorization flow and handles later token exchange and refresh. If the user revokes access, calls error out and you should prompt them to re-authorize.

### Callback address

When configuring the callback in the third-party OAuth2 provider, use the Agent Identity address for your region:

* **Beijing**: `https://auth.id.cn-beijing.volces.com/api/v1/oauth2callback`
* **Shanghai**: `https://auth.id.cn-shanghai.volces.com/api/v1/oauth2callback`
* **Guangzhou**: `https://auth.id.cn-guangzhou.volces.com/api/v1/oauth2callback`

After the user authorizes, the provider redirects the code and state to this address, and Agent Identity handles the token exchange.

## Example

<Warning>
  This example accesses real ECS resources. Configure the named OAuth provider with read permissions and complete user consent on first use. Prompts are not authorization controls; restrict write access in the provider and tool scope
</Warning>

The agent below connects to Volcengine ECS's MCP service through user-federation auth, querying instances after user authorization:

```python lines theme={null}
import asyncio
from veadk import Agent
from veadk.integrations.ve_identity import VeIdentityMcpToolset, oauth2_auth
from veadk.integrations.ve_identity.auth_processor import AuthRequestProcessor
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams

ecs_tools = VeIdentityMcpToolset(
    auth_config=oauth2_auth(
        provider_name="volc-ecs-oauth2-provider",
        scopes=["read"],
        auth_flow="USER_FEDERATION",
    ),
    connection_params=StreamableHTTPConnectionParams(url="https://ecs.mcp.volcbiz.com/ecs/mcp"),
)

agent = Agent(
    tools=[ecs_tools],
    system_prompt="You are a Volcengine ECS assistant. Only read instance information; do not modify resources or run server commands.",
    run_processor=AuthRequestProcessor(),
)

async def main():
    try:
        print(await agent.run("List my ECS instances"))
    finally:
        await ecs_tools.close()

asyncio.run(main())
```

For more detail, see the [Agent Identity documentation](https://www.volcengine.com/docs/86848/2080920?lang=zh).

## Authentication parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `provider_name` | `str` | `Required` | Existing credential provider name |
| `identity_client` | `IdentityClient` | `None` | Accepted by both factories; uses the default identity client if omitted |
| `region` | `str` | `None` | Accepted by both factories; uses identity service region configuration |
| `scopes` | `list[str]` | `None` | OAuth2 scopes; omission uses provider defaults |
| `auth_flow` | `str` | `None` | OAuth2 flow: M2M or USER\_FEDERATION; provider default if omitted |
| `callback_url` | `str` | `None` | Application callback for OAuth2 user consent |
| `force_authentication` | `bool` | `False` | Whether OAuth2 should force authentication |
| `response_for_auth_required` | `dict / str` | `None` | Response while OAuth2 user consent is required |
| `on_auth_url` | `Callable` | `None` | Callback for presenting the OAuth2 authorization URL |
| `oauth2_auth_poller` | `Callable` | `None` | Factory for an OAuth2 authorization poller |

`VeIdentityFunctionTool` requires `func` and `auth_config`. `into` defaults to `api_key` for API key auth or `access_token` for OAuth2 and must name a function parameter. The model does not supply that credential parameter; do not return it in tool output

Successful execution returns service data; pending consent may produce an authorization prompt. For failures, check the provider name, region, workload permissions, consent state, and third-party scopes without logging tokens
