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

# Serve as an API

> Turn agents into an HTTP service with streaming, sessions, and auth.

Product teams can connect web, mobile, and server-side clients to the same AgentOS backend. Registered agents become FastAPI services with streaming run routes, while AgentOS manages sessions, memory, knowledge, traces, evaluations, and approvals through the same API.

```python copilot.py theme={null}
from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS

db = PostgresDb(db_url="postgresql+psycopg://ai:ai@localhost:5532/ai")

agent = Agent(
    id="copilot",
    model=OpenAIResponses(id="gpt-5.5"),
    db=db,
    add_history_to_context=True,
    enable_agentic_memory=True,
)

agent_os = AgentOS(
    agents=[agent],
    db=db,
    cors_allowed_origins=[
        "http://localhost:3000",
        "https://app.yourproduct.com",
        "https://os.agno.com",
    ],
)
app = agent_os.get_app()

if __name__ == "__main__":
    agent_os.serve(app="copilot:app", port=7777)
```

Supplying `cors_allowed_origins` replaces the AgentOS defaults. Include every browser and AgentOS UI origin that needs to call the backend.

## Run the API

<Steps>
  <Snippet file="create-venv-step.mdx" />

  <Step title="Install dependencies">
    ```bash theme={null}
    uv pip install -U "agno[os]" openai sqlalchemy "psycopg[binary]"
    ```
  </Step>

  <Step title="Export your OpenAI API key">
    <CodeGroup>
      ```bash macOS / Linux theme={null}
      export OPENAI_API_KEY="your_openai_api_key_here"
      ```

      ```powershell Windows theme={null}
      $Env:OPENAI_API_KEY="your_openai_api_key_here"
      ```
    </CodeGroup>
  </Step>

  <Snippet file="run-pgvector-step.mdx" />

  <Step title="Start AgentOS">
    Save the code as `copilot.py`, then run:

    ```bash theme={null}
    python copilot.py
    ```
  </Step>
</Steps>

## Calling it from a surface

Every run endpoint takes the same shape, whether the caller is a browser widget or a backend job.

```bash theme={null}
curl -X POST http://localhost:7777/agents/copilot/runs \
  -F 'message=Summarize this thread' \
  -F 'user_id=sarah@acme.com' \
  -F 'session_id=thread-42' \
  -F 'stream=false'
```

```json theme={null}
{
  "run_id": "run_abc123",
  "session_id": "thread-42",
  "user_id": "sarah@acme.com",
  "agent_id": "copilot",
  "status": "COMPLETED",
  "content": "..."
}
```

After enabling authorization, a browser widget can stream with a JWT:

```javascript theme={null}
async function askCopilot(message, threadId, jwt) {
  const body = new FormData();
  body.append("message", message);
  body.append("session_id", threadId);
  body.append("stream", "true");

  const res = await fetch("https://os.yourproduct.com/agents/copilot/runs", {
    method: "POST",
    headers: { "Authorization": `Bearer ${jwt}` },
    body,
  });
  return res.body; // SSE stream into the UI
}
```

| Want                        | Pass                                            |
| --------------------------- | ----------------------------------------------- |
| Token stream for a live UI  | `stream=true` (Server-Sent Events, the default) |
| A single JSON response      | `stream=false`                                  |
| Long job, poll later        | `background=true` and `stream=false`            |
| User and thread attribution | `user_id` and a per-thread `session_id`         |

## AgentOS endpoints

| Endpoint group     | Covers                                                                                                       |
| ------------------ | ------------------------------------------------------------------------------------------------------------ |
| Runs               | Create, stream, cancel, run in background, resume disconnected streams                                       |
| Sessions           | Create, list, rename, delete, and pull every run in a session. Per-user enforcement requires user isolation. |
| Memory             | Create, update, delete, search user memories                                                                 |
| Knowledge          | Add, update, search, and delete indexed content                                                              |
| Traces and metrics | Per-run spans when tracing is enabled, plus token usage and model metrics                                    |
| Evaluations        | Run and retrieve agent and team evaluation results                                                           |
| Approvals          | List and resolve paused approval requests                                                                    |
| Schedules          | Create, update, trigger, enable, disable, and delete recurring runs                                          |

Browse the live OpenAPI spec at the `/docs` endpoint of your running AgentOS.

## Custom routes

`AgentOS` is a FastAPI app. Add routes for webhooks, dashboards, or product-specific endpoints. The agent is a regular Python object you can call from anywhere.

<Warning>
  A public Stripe webhook must read the raw request body and verify its `Stripe-Signature` with the endpoint secret before parsing or passing an event to the agent. Never accept an unverified decoded dictionary. See [Stripe's webhook signature guide](https://docs.stripe.com/webhooks/signature).
</Warning>

## Auth

Set `authorization=True` to require a valid JWT on protected central routes. Set `JWT_VERIFICATION_KEY` or `JWT_JWKS_FILE` before building the app. Add `user_isolation=True` to filter user-scoped data for non-admin callers.

```python theme={null}
from agno.os.config import AuthorizationConfig

agent_os = AgentOS(
    agents=[agent],
    db=db,
    authorization=True,
    authorization_config=AuthorizationConfig(user_isolation=True),
    cors_allowed_origins=[
        "http://localhost:3000",
        "https://app.yourproduct.com",
        "https://os.agno.com",
    ],
)
```

AgentOS validates the token before agent code runs. The JWT `sub` pins `user_id`, and the `scopes` claim drives RBAC. An optional `session_id` claim overrides the form value; otherwise the client supplies the session ID with the request.

## Next steps

| Task                          | Guide                                              |
| ----------------------------- | -------------------------------------------------- |
| Add Slack or browser surfaces | [Interfaces](/use-cases/product-agents/interfaces) |
| Lock down endpoints           | [Security and auth](/features/security-and-auth)   |

## Developer Resources

* [Agent API](/features/api)
* [Connect your AgentOS](/agent-os/connect-your-os)
* [Deploy](/deploy/introduction)
