> Documentation index: [/llms.txt](/llms.txt). Every page as one file: [/llms-full.txt](/llms-full.txt).

# Call an agent from an app

Call an agent from an app [#call-an-agent-from-an-app]

A hosted app's backend can run a platform agent; the run acts as the person using the app.

How it works [#how-it-works]

* When the app is registered it gets its own API key as the app secret `ALO_API_KEY`. The key stays in the app's backend and never reaches the browser.
* For each signed-in visitor, the app gateway adds a signed identity header, `X-Alo-App-Identity`, valid for 5 minutes. The app's backend sends it along with its key.
* The platform runs the agent as that person: their access, their credits, and a chat saved as theirs and hidden from their chat list.
* A visitor who is not signed in, for example on a `public` app, has no identity. The call returns `401` with `code` `APP_VIEWER_IDENTITY_REQUIRED`.
* The run can use only the connections the app declares.

Add an agent to an app [#add-an-agent-to-an-app]

Ask App Builder in the app's chat. Two common shapes:

| You want                                | Ask for                                                                                                                           |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| A chat assistant inside the app         | `Add an assistant to this app that uses the agent Contract Reviewer.` With no agent named it uses the default agent.              |
| A button that runs an agent on a record | `Add a "Summarize" button: the backend asks Contract Reviewer for a 3-sentence summary of the record and saves it on the record.` |

App Builder writes the backend route with the platform client the app template ships:

```python
from alo_agents_client import AloAgentsClient
from connector_client import get_request_app_identity

client = AloAgentsClient(app_identity=get_request_app_identity())
summary = ""
for event in client.stream_chat("Summarize contract 12 in 3 sentences.", agent_id=12):
    if event["type"] == "text":
        summary += event["delta"]
    elif event["type"] == "error":
        raise RuntimeError(event["message"])
```

`stream_chat` yields events of type `text`, `reasoning`, `tool`, `run_started`, `run_finished` and `error`.

Limits [#limits]

| Limit                          | Value                              |
| ------------------------------ | ---------------------------------- |
| Visitors who are not signed in | Refused, `401`                     |
| Who pays                       | The signed-in person               |
| Connections                    | Only those the app declares        |
| Client timeout                 | 120 seconds per request by default |
