Skip to content

Commit a4be71d

Browse files
committed
Give the Pydantic example a key, a free port, and the shipped model default
The endpoint read no header, which is the one thing an example must not teach now that the server sends a Bot's key on every run: it takes a run from anyone who can reach the port. Guarded by REQUIRE_KEY, the same optional guard the LangGraph example carries. 4202 sits in the band the in-box agents use, 4200 and 4201. The examples step by a hundred, 4300 and 4400, and 4500 is the supervisor, so 4600. gpt-4.1 is not what this deployment ships; gpt-5.5 is the default everywhere else. Also record that Pydantic AI calls /responses rather than /v1/chat/completions, which decides whether a given gateway can serve this at all, and ignore the egg-info that the README's own install step leaves behind.
1 parent e4fe3a8 commit a4be71d

3 files changed

Lines changed: 22 additions & 7 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
__pycache__/
22
*.pyc
33
.venv/
4+
*.egg-info/

‎examples/pydantic-ai-bot/README.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,21 @@ pip install -e .
2828
OPENAI_API_KEY=... python src/app.py
2929
```
3030

31-
It listens on `http://localhost:4202/ag-ui` (`PORT` to change) and answers `GET /health`.
31+
It listens on `http://localhost:4600/ag-ui` (`PORT` to change) and answers `GET /health`.
3232

3333
| Variable | Default | Meaning |
3434
| ---------------- | --------- | ---------------------------------------------------- |
3535
| `OPENAI_API_KEY` | required | Read by Pydantic AI's OpenAI provider. |
36-
| `BOT_MODEL` | `gpt-4.1` | Model the agent runs. Any tool-calling model. |
37-
| `PORT` | `4202` | Port the AG-UI endpoint listens on. |
36+
| `BOT_MODEL` | `gpt-5.5` | Model the agent runs. Any tool-calling model. |
37+
| `PORT` | `4600` | Port the AG-UI endpoint listens on. |
38+
| `REQUIRE_KEY` | unset | When set, `/ag-ui` refuses a run whose `authorization` header does not match. |
3839

3940
`OPENAI_BASE_URL` points the OpenAI provider at a compatible gateway, the same way the rest of the
40-
deployment is configured (see [docs/configuration.md](../../docs/configuration.md)).
41+
deployment is configured (see [docs/configuration.md](../../docs/configuration.md)). Note which API
42+
that gateway has to serve: Pydantic AI calls `/responses`, not `/v1/chat/completions`. A gateway
43+
offering only chat completions will not answer this example, and the reverse of the constraint the
44+
two TypeScript Bots carry, which is that they speak chat completions and so cannot use the models
45+
that require Responses.
4146

4247
## Register it
4348

@@ -51,7 +56,7 @@ agents:
5156
title: Research
5257
role_description: Research on a governed computer, written in Pydantic AI.
5358
type: remote-ag-ui
54-
endpoint: ${PYDANTIC_BOT_AG_UI_URL:-http://localhost:4202/ag-ui}
59+
endpoint: ${PYDANTIC_BOT_AG_UI_URL:-http://localhost:4600/ag-ui}
5560
```
5661
5762
## Notes

‎examples/pydantic-ai-bot/src/app.py‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from starlette.responses import JSONResponse, Response
2121
from starlette.routing import Route
2222

23-
MODEL = os.environ.get("BOT_MODEL", "gpt-4.1")
23+
MODEL = os.environ.get("BOT_MODEL", "gpt-5.5")
2424

2525
# A real Pydantic AI agent with its own model client. It defines no tools of its own: the tools it
2626
# may call arrive per run from the surface (see below), so this file never names `computer_navigate`
@@ -42,12 +42,21 @@
4242
async def ag_ui(request: Request) -> Response:
4343
"""One POST carrying a ``RunAgentInput``, a stream of AG-UI events back.
4444
45+
Guarded by ``REQUIRE_KEY`` when it is set, the same as the LangGraph example: OpenBot sends the
46+
Bot's key on every run, and an endpoint that never reads the header accepts a run from anyone who
47+
can reach the port. Optional because a developer running this by hand has no key to send, and
48+
refusing them would teach nothing.
49+
4550
``AGUIAdapter.dispatch_request`` reads the run input, exposes ``input.tools`` to the model as
4651
external (frontend) tools, runs the agent, and returns a streaming AG-UI Server-Sent-Events
4752
response. The tool loop stays on the client, exactly as it does for the Bot in the box: a tool
4853
call is emitted, this run ends, and OpenBot executes it through the policy gateway before starting
4954
the next run with the result. That is why this file can drive a browser it has no access to.
5055
"""
56+
required_key = os.environ.get("REQUIRE_KEY")
57+
if required_key and request.headers.get("authorization") != required_key:
58+
print("refused a run: wrong or missing key")
59+
return JSONResponse({"error": "Unauthorized"}, status_code=401)
5160
return await AGUIAdapter.dispatch_request(request, agent=agent)
5261

5362

@@ -66,6 +75,6 @@ async def health(_: Request) -> Response:
6675
if __name__ == "__main__":
6776
import uvicorn
6877

69-
port = int(os.environ.get("PORT", "4202"))
78+
port = int(os.environ.get("PORT", "4600"))
7079
print(f"pydantic-ai-bot listening on http://localhost:{port}/ag-ui (model {MODEL})")
7180
uvicorn.run(app, host="0.0.0.0", port=port)

0 commit comments

Comments
 (0)