---
name: uapi-agent-authoring
description: Guidelines for writing correct Strands agents on the Universal API platform
---

## Instructions

When writing agent source code for the Universal API platform, follow these rules:

### Entry Point
- Define a `create_agent()` function that returns `(agent, mcp_clients)`.
- For voice agents, define `create_bidi_agent()` instead.
- `session_manager` is auto-injected — use it for multi-turn conversations.

### Available Environment
- `UNIVERSALAPI_BEARER_TOKEN` — caller's auth token for MCP/API calls.
- `UAPI_KEYS_JSON` — JSON dict of caller's stored 3rd-party API keys.
- `BEDROCK_MODEL_ID` — optional model override from the chat request.

### Sandbox Restrictions
- No `subprocess`, `socket`, `ctypes`, `exec`, `eval`, `compile`.
- `os` is restricted: `os.environ` (read allowed env), `os.path`, `os.getcwd`.
- `open()` writes only to `/tmp`.
- Allowed: `json`, `datetime`, `re`, `math`, `collections`, `csv`, `statistics`, `httpx`, `boto3`, `strands`, `mcp`.

### MCP Server Connection Pattern
```python
from strands.tools.mcp import MCPClient
from mcp.client.streamable_http import streamablehttp_client

bearer_token = os.environ.get('UNIVERSALAPI_BEARER_TOKEN', '')
mcp_client = MCPClient(
    lambda: streamablehttp_client(
        "https://mcp.api.universalapi.co/mcp/s/{owner}/{slug}",
        headers={"Authorization": f"Bearer {bearer_token}"}
    )
)
agent = Agent(model=model, tools=[mcp_client])
return agent, [mcp_client]  # always return clients for cleanup
```

### Best Practices
- Always return MCP clients in the tuple for proper cleanup.
- Use `us.anthropic.claude-sonnet-4-20250514-v1:0` as the default model.
- Set a clear `system_prompt` describing the agent's purpose.
- Keep source code under 32KB for fast cold starts.