Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/docs/agents/chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ or the turn fails with `TypeError`.

## Call a model

!!! tip "Calling a model with tools"
To have a model call your Python methods, use the
[Pydantic AI harness](pydantic-ai.md): `WorkersAIModel` plus `@tool` methods.
The harness runs on `Agent`, not `AIChatAgent`, and streams with `session.stream()`.

The SDK doesn't call a model or ship provider adapters. Inside
`on_chat_message`, convert `self.messages` to your provider's format, call it
with your own client, and yield its text as it streams. A converter for
Expand Down
46 changes: 45 additions & 1 deletion docs/docs/agents/coming-from-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,50 @@ with your own client. There's no `onFinish` callback, so use
`on_chat_response`. Cancellation replaces the `abortSignal`, so a stopped
turn gets `asyncio.CancelledError`. See [Build a chat agent](chat.md).

## Chat with tools

`streamText({ model, tools })` maps to `PydanticAIHarness`. Pydantic AI runs
the tool loop, and `@tool` methods are the tools.

**Python**

```python
import pydantic_ai

from agents import Agent, tool
from agents.harness.pydantic_ai import PydanticAIHarness, WorkersAIModel


class Notes(Agent):
def __init__(self, ctx, env):
super().__init__(ctx, env)
model = WorkersAIModel("@cf/qwen/qwen3-30b-a3b-fp8", binding=env.AI)
agent = pydantic_ai.Agent(model, instructions="You keep the user's notes.")
self.harness = self.use(PydanticAIHarness("notes", agent, target=self))

@tool
async def add_note(self, text: str) -> str:
"""Save a note."""
return "Saved"
```

**TypeScript**

```typescript
async onChatMessage() {
return streamText({
model: workersai("@cf/qwen/qwen3-30b-a3b-fp8"),
messages: convertToModelMessages(this.messages),
tools: { addNote },
}).toUIMessageStreamResponse();
}
```

The harness stores the conversation itself, so it runs on `Agent`, not
`AIChatAgent`. Call `self.harness.prompt(text)` for the reply, or
`session.stream(text)` to stream it. See
[Run a Pydantic AI agent in a Durable Object](pydantic-ai.md).

## Errors

The SDK's own exceptions subclass `AgentsException`, so
Expand All @@ -126,7 +170,7 @@ type, raises `TypeError`, `ValueError` or `RuntimeError` instead.
| --------------------------------------------------- | -------------------------------------------- |
| `McpAgent` and MCP's RPC transport | Not ported. Use [`create_mcp_handler`](mcp-server.md). |
| MCP's legacy SSE transport | Not ported. [`add_mcp_server`](mcp-client.md) speaks Streamable HTTP. |
| Chat client tools and approvals | Not ported. |
| Chat client tools and approvals | Not ported. Server-side tools and approvals run in the [Pydantic AI harness](pydantic-ai.md#approve-tool-calls). |
| Recovery of interrupted chat turns | Not ported. |
| `props` in `routeAgentRequest` and `getAgentByName` | Not ported. |
| Think, voice, email, channels, workflows, browser | Not ported. |
Expand Down
Loading