agents 0.30.1 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/{agent-routing-CDbpVjYq.d.ts → agent-routing-vVMA7m8Y.d.ts} +69 -608
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-C8DH8Yii.d.ts → agent-tools-gGXXkf1z.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/agent-tools.js +0 -1
- package/dist/agent-tools.js.map +1 -1
- package/dist/{ai-iXw0uOGj.d.ts → ai-CDn3Abax.d.ts} +30 -4
- package/dist/{ai-sdk-DRPh2rRa.js → ai-sdk-Kon40i0q.js} +2 -36
- package/dist/ai-sdk-Kon40i0q.js.map +1 -0
- package/dist/browser/ai.d.ts +1 -1
- package/dist/browser/ai.js +16 -3
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +64 -16
- package/dist/browser/index.js +4 -4
- package/dist/browser/tools/ai-sdk.d.ts +7 -5
- package/dist/browser/tools/ai-sdk.js +4 -4
- package/dist/browser/tools/ai-sdk.js.map +1 -1
- package/dist/browser/tools/pi.d.ts +9 -15
- package/dist/browser/tools/pi.js +6 -14
- package/dist/browser/tools/pi.js.map +1 -1
- package/dist/browser/tools/tanstack-ai.d.ts +48 -25
- package/dist/browser/tools/tanstack-ai.js +8 -4
- package/dist/browser/tools/tanstack-ai.js.map +1 -1
- package/dist/{browser-DccPw_wW.js → browser-1eUbPvC2.js} +413 -14
- package/dist/browser-1eUbPvC2.js.map +1 -0
- package/dist/{browser-DlXhSAdf.d.ts → browser-D9RNpJuT.d.ts} +254 -20
- package/dist/browser-tool-BhjCcNVE.d.ts +71 -0
- package/dist/browser-tool-DRan7Lk6.js +497 -0
- package/dist/browser-tool-DRan7Lk6.js.map +1 -0
- package/dist/capability-id-B3J8Nok_.js +13 -0
- package/dist/capability-id-B3J8Nok_.js.map +1 -0
- package/dist/catalog-BpOejOsE.js +239 -0
- package/dist/catalog-BpOejOsE.js.map +1 -0
- package/dist/catalog-BpiVV1OF.d.ts +173 -0
- package/dist/chat/index.d.ts +2 -2
- package/dist/chat-sdk/index.d.ts +3 -3
- package/dist/chat-sdk/index.js +1 -1
- package/dist/client-4OlMIJx-.js.map +1 -1
- package/dist/{client-BnYbNT3z.js → client-DMWujQJ1.js} +68 -244
- package/dist/client-DMWujQJ1.js.map +1 -0
- package/dist/{client-C27CtRZr.d.ts → client-eSfgYvd3.d.ts} +9 -7
- package/dist/client.d.ts +1 -1
- package/dist/{cloudflare-Dzvc7V2N.js → cloudflare-CUUm_9q9.js} +26 -4
- package/dist/cloudflare-CUUm_9q9.js.map +1 -0
- package/dist/{connector-DAXBOIIi.js → connector-CM-uuxKM.js} +96 -8
- package/dist/connector-CM-uuxKM.js.map +1 -0
- package/dist/{connector-20DJ6p4k.d.ts → connector-DZ71EjE-.d.ts} +109 -9
- package/dist/{do-oauth-client-provider-DfsUcpc3.d.ts → do-oauth-client-provider-DtNqv7oj.d.ts} +26 -2
- package/dist/{index-YSKgfgg9.d.ts → emitter-BJZtCVjQ.d.ts} +6 -140
- package/dist/emitter-DPOVcCln.js +15 -0
- package/dist/emitter-DPOVcCln.js.map +1 -0
- package/dist/experimental/channels/web/index.js +1 -1
- package/dist/experimental/webmcp.js +1 -1
- package/dist/{handler-stateless-Bly_nSH3.js → handler-stateless-B5hU3dxK.js} +35 -2
- package/dist/handler-stateless-B5hU3dxK.js.map +1 -0
- package/dist/{handler-stateless-DxYpJ_XF.d.ts → handler-stateless-C90kD5_R.d.ts} +3 -47
- package/dist/harness/container/index.d.ts +15 -15
- package/dist/harness/container/index.js +0 -1
- package/dist/harness/container/index.js.map +1 -1
- package/dist/harness/container/runtime/index.js +2 -2
- package/dist/harness/opencode/index.js +0 -1
- package/dist/harness/opencode/index.js.map +1 -1
- package/dist/harness/pi/index.d.ts +15 -7
- package/dist/harness/pi/index.js +74 -151
- package/dist/harness/pi/index.js.map +1 -1
- package/dist/harness/think/index.d.ts +2 -1
- package/dist/{images-xaDv2Fqe.js → images-CfuRCjwq.js} +1 -5
- package/dist/images-CfuRCjwq.js.map +1 -0
- package/dist/{index-DCxk3OSJ.d.ts → index-8k4qsX1T.d.ts} +2 -28
- package/dist/index.d.ts +15 -16
- package/dist/index.js +3 -3
- package/dist/internal-hosts-Kfp5A392.d.ts +230 -0
- package/dist/internal-kmw70xwR.js.map +1 -1
- package/dist/invoker-BC1SZ3q1.js +26 -0
- package/dist/invoker-BC1SZ3q1.js.map +1 -0
- package/dist/invoker-DoLFPJZV.d.ts +21 -0
- package/dist/markdown-BZ-VLtA1.js +86 -0
- package/dist/markdown-BZ-VLtA1.js.map +1 -0
- package/dist/mcp/client/do-oauth-client-provider.d.ts +4 -2
- package/dist/mcp/client/do-oauth-client-provider.js +15 -1
- package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/client/index.d.ts +15 -1
- package/dist/mcp/client/index.js +2 -2
- package/dist/mcp/client/x402.d.ts +7 -5
- package/dist/mcp/client/x402.js +34 -1
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +561 -27
- package/dist/mcp/index.js +180 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server/index.d.ts +1 -1
- package/dist/mcp/server/index.js +1 -1
- package/dist/models/ai-sdk/index.d.ts +2 -2
- package/dist/models/ai-sdk/index.js +1 -1
- package/dist/models/opencode/index.d.ts +2 -2
- package/dist/models/opencode/index.js +1 -1
- package/dist/models/pi-ai/index.d.ts +3 -28
- package/dist/models/pi-ai/index.js +160 -18
- package/dist/models/pi-ai/index.js.map +1 -1
- package/dist/observability/ai/index.js +1 -2
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/observability/index.d.ts +170 -9
- package/dist/observability/index.js +386 -11
- package/dist/observability/index.js.map +1 -1
- package/dist/protocol-BEgrJYC5.d.ts +29 -29
- package/dist/react.d.ts +2 -2
- package/dist/resource-B59OV2a2.js +325 -0
- package/dist/resource-B59OV2a2.js.map +1 -0
- package/dist/routing/index.d.ts +1 -1
- package/dist/script-CFDLTk5b.d.ts +91 -0
- package/dist/script-workspace-BpdAYq1R.d.ts +41 -0
- package/dist/serializable.d.ts +1 -1
- package/dist/{session-store-yvwq1f9x.js → session-7CDgVE0z.js} +455 -33
- package/dist/session-7CDgVE0z.js.map +1 -0
- package/dist/{session-store-_IK6dV-w.d.ts → session-store-B7Ca-u1t.d.ts} +8 -1
- package/dist/settings-Dk2il2Hf.js.map +1 -1
- package/dist/skill-DRBcIBjC.d.ts +221 -0
- package/dist/skills/index.d.ts +275 -36
- package/dist/skills/index.js +265 -1534
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/runner.d.ts +37 -0
- package/dist/skills/runner.js +912 -0
- package/dist/skills/runner.js.map +1 -0
- package/dist/skills/tools/ai-sdk.d.ts +36 -0
- package/dist/skills/tools/ai-sdk.js +94 -0
- package/dist/skills/tools/ai-sdk.js.map +1 -0
- package/dist/source-9RQzlEhM.d.ts +112 -0
- package/dist/{src-DfLzdwlK.js → src-DoGNJ4Ud.js} +21 -6
- package/dist/src-DoGNJ4Ud.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/tool-CTp72Jb_.d.ts +10 -10
- package/dist/tool-CxKsvxjm.js.map +1 -1
- package/dist/tool-DkT_DJBm.js.map +1 -1
- package/dist/tool-DoVberpN.d.ts +22 -22
- package/dist/tool-helpers-BI7ifO2S.js +255 -0
- package/dist/tool-helpers-BI7ifO2S.js.map +1 -0
- package/dist/{transport-CPh7YGiw.d.ts → transport-5moD2pW5.d.ts} +1 -43
- package/dist/types-D2naO3rA.d.ts +49 -0
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +10 -258
- package/dist/vite.js.map +1 -1
- package/dist/voice/index.d.ts +1 -1
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-CyoeosdO.js → websockets-C6SJtWCJ.js} +1 -2
- package/dist/{websockets-CyoeosdO.js.map → websockets-C6SJtWCJ.js.map} +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +0 -1
- package/dist/workflows.js.map +1 -1
- package/docs/browse-the-web.md +247 -413
- package/docs/harnesses/pi.md +36 -30
- package/docs/index.md +4 -4
- package/docs/mcp-client.md +25 -1
- package/docs/mcp-servers.md +26 -7
- package/docs/models-pi-ai.md +9 -11
- package/docs/models.md +1 -8
- package/docs/observability.md +5 -3
- package/docs/securing-mcp-servers.md +113 -302
- package/package.json +31 -17
- package/dist/ai-sdk-DRPh2rRa.js.map +0 -1
- package/dist/browser-DccPw_wW.js.map +0 -1
- package/dist/browser-tool-B1mhifin.js +0 -616
- package/dist/browser-tool-B1mhifin.js.map +0 -1
- package/dist/browser-tool-Cxjk5sgG.d.ts +0 -92
- package/dist/client-BnYbNT3z.js.map +0 -1
- package/dist/cloudflare-Dzvc7V2N.js.map +0 -1
- package/dist/connector-DAXBOIIi.js.map +0 -1
- package/dist/handler-stateless-Bly_nSH3.js.map +0 -1
- package/dist/images-xaDv2Fqe.js.map +0 -1
- package/dist/index-iv9FTXX9.d.ts +0 -311
- package/dist/invoker-CG0_p_Wq.d.ts +0 -20
- package/dist/invoker-CHMnoxIA.js +0 -57
- package/dist/invoker-CHMnoxIA.js.map +0 -1
- package/dist/session-store-yvwq1f9x.js.map +0 -1
- package/dist/skills/compile.d.ts +0 -40
- package/dist/skills/compile.js +0 -65
- package/dist/skills/compile.js.map +0 -1
- package/dist/src-DfLzdwlK.js.map +0 -1
- package/dist/tool-helpers-O5BDVEAY.js +0 -58
- package/dist/tool-helpers-O5BDVEAY.js.map +0 -1
- package/skills-module.d.ts +0 -22
package/docs/harnesses/pi.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Pi harness
|
|
2
|
+
title: Pi harness
|
|
3
3
|
pcx_content_type: get-started
|
|
4
|
-
description: Host pi-durable sessions in a Durable Object with the
|
|
4
|
+
description: Host pi-durable sessions in a Durable Object with the PiHarness lifecycle capability. Connect a pi-ai model, add tools and skills, and keep sessions running across eviction.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
`PiHarness` hosts [pi-durable](https://github.com/earendil-works/pi/tree/main/packages/durable) in a Durable Object. It opens Pi over the object's SQLite database and connects Pi's sessions to the Agents SDK lifecycle, which wakes sessions with work after eviction.
|
|
7
|
+
`PiHarness` hosts [pi-durable](https://github.com/earendil-works/pi/tree/main/packages/durable) in a Durable Object. It opens Pi over the object's SQLite database and connects Pi's sessions to the Agents SDK lifecycle, which wakes sessions with work after eviction.
|
|
8
8
|
|
|
9
9
|
Pi owns everything about a run: the transcript, the inbox of steers and follow-ups, generation, tool calls, retries, and crash recovery. `PiHarness` supplies the storage and the wake. It does not provide a chat protocol or user interface. Your application chooses how clients reach sessions, such as WebSockets, HTTP, or RPC.
|
|
10
10
|
|
|
@@ -21,13 +21,14 @@ The three Pi packages are optional peer dependencies of `agents`, at `~1.4.0`. p
|
|
|
21
21
|
`PiHarness` uses a factory function to construct Pi's `Harness` so it can be instantiated lazily:
|
|
22
22
|
|
|
23
23
|
```ts
|
|
24
|
+
import { DurableObject } from "cloudflare:workers";
|
|
24
25
|
import { createModels } from "@earendil-works/pi-ai/models";
|
|
25
26
|
import { createRegistry, Harness } from "@earendil-works/pi-durable";
|
|
26
|
-
import { Agent } from "agents";
|
|
27
27
|
import { PiHarness } from "agents/harness/pi";
|
|
28
|
+
import { Lifecycle } from "agents/lifecycle";
|
|
28
29
|
import { createAI } from "agents/models/pi-ai";
|
|
29
30
|
|
|
30
|
-
export class Assistant extends
|
|
31
|
+
export class Assistant extends DurableObject<Env> {
|
|
31
32
|
ai = createAI({ binding: this.env.AI });
|
|
32
33
|
registry = createRegistry();
|
|
33
34
|
|
|
@@ -42,15 +43,12 @@ export class Assistant extends Agent<Env> {
|
|
|
42
43
|
);
|
|
43
44
|
},
|
|
44
45
|
defaults: {
|
|
45
|
-
model: this.ai("@cf/zai-org/glm-
|
|
46
|
+
model: this.ai("@cf/zai-org/glm-5.3-flash"),
|
|
46
47
|
thinkingLevel: "low"
|
|
47
48
|
}
|
|
48
49
|
});
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
super(ctx, env);
|
|
52
|
-
this.lifecycle.use(this.harness);
|
|
53
|
-
}
|
|
51
|
+
lifecycle = Lifecycle.install(this).use(this.harness);
|
|
54
52
|
|
|
55
53
|
async ask(prompt: string) {
|
|
56
54
|
return (await this.harness.prompt(prompt)).text;
|
|
@@ -58,6 +56,8 @@ export class Assistant extends Agent<Env> {
|
|
|
58
56
|
}
|
|
59
57
|
```
|
|
60
58
|
|
|
59
|
+
`PiHarness` is a Lifecycle capability, so it runs on a plain Durable Object. `Lifecycle.install(this)` gives the object its startup, alarms and job queue, and `.use(this.harness)` installs the harness on it. The object needs a SQLite migration in your Wrangler configuration, like any Durable Object that uses SQLite storage. To use it from an `Agent`, which already has a lifecycle, call `this.lifecycle.use(this.harness)` in the constructor instead.
|
|
60
|
+
|
|
61
61
|
| Option | What it is |
|
|
62
62
|
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
63
|
| `harness` | Required. Receives `{ storage, context, onWake }` and returns Pi's `Harness`, usually from `Harness.open`. Pass `onWake` to `Harness.open`, so the object can hibernate while Pi's tasks sleep (see [How recovery works](#how-recovery-works)). Models, the registry, `settings`, `env` and `onReport` are all yours to build here. |
|
|
@@ -118,13 +118,19 @@ Pi's extensions can do more: hooks on model requests and tool calls (`hook(ToolT
|
|
|
118
118
|
|
|
119
119
|
### Skills
|
|
120
120
|
|
|
121
|
-
`skills(sources)` turns `agents/skills` sources (refer to [Agent Skills](../../think/index.md#agent-skills)) into a Pi extension named `agents.skills`. It has two tools, `activate_skill` and `read_skill_resource`, and a `skills` section that lists the skills. Install it in the factory, since it reads the sources:
|
|
121
|
+
`skills(sources)` turns `agents/skills` sources (refer to [Agent Skills](../../think/index.md#agent-skills)) into a Pi extension named `agents.skills`. It has two tools, `activate_skill` and `read_skill_resource`, and a `skills` section that lists the skills. Sources can read skills from a Computer Workspace (`workspace()`), an R2 bucket (`r2()`), or code (`manifest()`). Install it in the factory, since it reads the sources:
|
|
122
122
|
|
|
123
123
|
```ts
|
|
124
124
|
import { skills } from "agents/harness/pi";
|
|
125
|
+
import * as agentSkills from "agents/skills";
|
|
125
126
|
|
|
126
127
|
harness: async ({ storage, context, onWake }) => {
|
|
127
|
-
this.registry.install(
|
|
128
|
+
this.registry.install(
|
|
129
|
+
await skills([
|
|
130
|
+
agentSkills.workspace(workspace), // /workspace/.agents/skills
|
|
131
|
+
agentSkills.r2(this.env.SKILLS_BUCKET, { prefix: "skills/" })
|
|
132
|
+
])
|
|
133
|
+
);
|
|
128
134
|
return Harness.open(
|
|
129
135
|
storage,
|
|
130
136
|
{ models, registry: this.registry, onWake },
|
|
@@ -133,7 +139,7 @@ harness: async ({ storage, context, onWake }) => {
|
|
|
133
139
|
};
|
|
134
140
|
```
|
|
135
141
|
|
|
136
|
-
The
|
|
142
|
+
The sources are read once, when the factory builds the extension. The tools and their output match `@cloudflare/think`, so a skill behaves the same in both.
|
|
137
143
|
|
|
138
144
|
### Browser
|
|
139
145
|
|
|
@@ -149,7 +155,7 @@ harness: async ({ storage, context, onWake }) => {
|
|
|
149
155
|
this.registry.install({
|
|
150
156
|
name: "browser",
|
|
151
157
|
tools: [
|
|
152
|
-
browserTool({
|
|
158
|
+
browserTool({ browser: this.browser, loader: this.env.LOADER })
|
|
153
159
|
]
|
|
154
160
|
});
|
|
155
161
|
return Harness.open(
|
|
@@ -162,7 +168,7 @@ harness: async ({ storage, context, onWake }) => {
|
|
|
162
168
|
readonly lifecycle = Lifecycle.install(this).use(this.browser).use(this.harness);
|
|
163
169
|
```
|
|
164
170
|
|
|
165
|
-
It needs a `browser` binding, a `LOADER` Worker Loader binding, and `
|
|
171
|
+
It needs a `browser` binding, a `LOADER` Worker Loader binding, and `@cloudflare/codemode` installed (only until the deprecated codemode browser APIs are removed from `agents/browser`). Screenshots come back as images, and each conversation works in its own tab. Refer to [Persistent browser](../browse-the-web.md#persistent-browser) for how it behaves.
|
|
166
172
|
|
|
167
173
|
## Work with sessions
|
|
168
174
|
|
|
@@ -174,7 +180,7 @@ const { text } = await this.harness.prompt("What is 47 × 19?");
|
|
|
174
180
|
|
|
175
181
|
// Another session, on a cheaper model.
|
|
176
182
|
const session = await this.harness.sessions.create();
|
|
177
|
-
await session.setModel(this.ai("@cf/zai-org/glm-
|
|
183
|
+
await session.setModel(this.ai("@cf/zai-org/glm-5.3-flash"));
|
|
178
184
|
|
|
179
185
|
// Durable once it returns; the same operation id twice is one submission.
|
|
180
186
|
const receipt = await session.submit("Summarize the latest report", {
|
|
@@ -183,20 +189,20 @@ const receipt = await session.submit("Summarize the latest report", {
|
|
|
183
189
|
const result = await session.wait(receipt.operationId);
|
|
184
190
|
```
|
|
185
191
|
|
|
186
|
-
| Call | What it does
|
|
187
|
-
| ------------------------------------------------- |
|
|
188
|
-
| `prompt(input)` | Submits and waits: the answer, and the transcript after it.
|
|
189
|
-
| `submit(input, { operationId, whenBusy, entry })` | Hands the input to Pi and returns as soon as Pi has saved it, without waiting for the model. If the session is already working, the input waits until that work finishes. With `whenBusy: "steer"`, it joins the running work instead, after the current round of tool calls. `entry` records where the input came from (see below). |
|
|
190
|
-
| `wait(operationId, signal?)` | The operation's result once Pi settles it. Aborting `signal` stops only the wait, not the work.
|
|
191
|
-
| `steer(input)` | `submit` with `whenBusy: "steer"`.
|
|
192
|
-
| `abort(operationId?)` | Withdraws a queued operation, or with no id, stops everything running in the session.
|
|
193
|
-
| `pending()` | Operations Pi has not settled yet: queued, part of the running work, or `parked` (see [How recovery works](#how-recovery-works)).
|
|
194
|
-
| `retry()` | Runs again the tasks Pi's restart limit parked in the session's work. Resolves `false` when nothing was parked.
|
|
195
|
-
| `messages()` | Pi's transcript entries since the newest reset.
|
|
196
|
-
| `events()` | Pi's agent events: a `snapshot`, then one batch per commit.
|
|
197
|
-
| `reset(handoff?)` | Starts a new context, optionally from a handoff note.
|
|
198
|
-
| `setModel(model)` | Changes this session's model.
|
|
199
|
-
| `busy()` | Whether a run is going.
|
|
192
|
+
| Call | What it does |
|
|
193
|
+
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
194
|
+
| `prompt(input)` | Submits and waits: the answer, and the transcript after it. |
|
|
195
|
+
| `submit(input, { operationId, whenBusy, entry })` | Hands the input to Pi and returns as soon as Pi has saved it, without waiting for the model. If the session is already working, the input waits until that work finishes. With `whenBusy: "steer"`, it joins the running work instead, after the current round of tool calls. With `whenBusy: "reject"`, it is not admitted: `submit` rejects with Pi's `ConversationBusy` and nothing is saved, so the same `operationId` can be submitted again later. `entry` records where the input came from (see below). |
|
|
196
|
+
| `wait(operationId, signal?)` | The operation's result once Pi settles it. Aborting `signal` stops only the wait, not the work. |
|
|
197
|
+
| `steer(input)` | `submit` with `whenBusy: "steer"`. |
|
|
198
|
+
| `abort(operationId?)` | Withdraws a queued operation, or with no id, stops everything running in the session. |
|
|
199
|
+
| `pending()` | Operations Pi has not settled yet: queued, part of the running work, or `parked` (see [How recovery works](#how-recovery-works)). |
|
|
200
|
+
| `retry()` | Runs again the tasks Pi's restart limit parked in the session's work. Resolves `false` when nothing was parked. |
|
|
201
|
+
| `messages()` | Pi's transcript entries since the newest reset. |
|
|
202
|
+
| `events()` | Pi's agent events: a `snapshot`, then one batch per commit. |
|
|
203
|
+
| `reset(handoff?)` | Starts a new context, optionally from a handoff note. |
|
|
204
|
+
| `setModel(model)` | Changes this session's model. |
|
|
205
|
+
| `busy()` | Whether a run is going. |
|
|
200
206
|
|
|
201
207
|
`harness.prompt()`, `submit()`, `wait()`, `abort()`, `retry()`, `messages()` and `pending()` act on the root session, or on `{ session }`. `harness.sessions` has `create()`, `fork(from)`, `get(id)` and `list()`, which includes sessions subagents created. `ROOT_SESSION` is the root's id.
|
|
202
208
|
|
package/docs/index.md
CHANGED
|
@@ -49,7 +49,7 @@ The Lifecycle runs startup, routes requests to capabilities, and owns the object
|
|
|
49
49
|
|
|
50
50
|
## Harnesses
|
|
51
51
|
|
|
52
|
-
- [Pi harness
|
|
52
|
+
- [Pi harness](./harnesses/pi.md) - Host pi-durable sessions in a Durable Object with durable storage and lifecycle wakeups
|
|
53
53
|
- [Think harness (Experimental)](./harnesses/think.md) - Run Think's agent loop as a Lifecycle capability, with transcripts in Sessions, output in Streams, and turns that survive eviction
|
|
54
54
|
- [Think (Experimental)](https://github.com/cloudflare/agents/blob/main/docs/think/index.md) - Opinionated chat agent with built-in memory, tools, and streaming. Extends `Think`, which builds on `Agent`.
|
|
55
55
|
|
|
@@ -136,12 +136,12 @@ Building your own harness? Sessions stores the conversation, Streams holds durab
|
|
|
136
136
|
- TODO: [AI SDK Integration](./ai-sdk.md) - Using Vercel AI SDK with agents
|
|
137
137
|
- TODO: [TanStack Integration](./tanstack.md) - Using TanStack AI with agents
|
|
138
138
|
- TODO: [Using AI Models](./using-ai-models.md) - OpenAI, Anthropic, Workers AI, and other providers
|
|
139
|
-
- [Models
|
|
140
|
-
- [Models for pi-ai
|
|
139
|
+
- [Models](./models.md) - `createAI` — one AI SDK provider for Workers AI and third-party catalog models, same string space
|
|
140
|
+
- [Models for pi-ai](./models-pi-ai.md) - `createAI` for pi-ai: Workers AI ids and third-party models through AI Gateway, as a pi-ai provider
|
|
141
141
|
- [Context (Experimental)](./context.md) - System-prompt blocks, frozen prompts, writable/searchable/loadable providers, and their tools
|
|
142
142
|
- [Workspace (Experimental)](https://github.com/cloudflare/agents/blob/main/docs/shell/index.md) - Durable virtual filesystem backed by SQLite + R2
|
|
143
143
|
- [Codemode (Experimental)](./codemode.md) - LLM-generated executable code for tool orchestration
|
|
144
|
-
- [Browse the Web
|
|
144
|
+
- [Browse the Web](./browse-the-web.md) - Full CDP access for web inspection, scraping, and debugging
|
|
145
145
|
- [Search the Web (Beta)](./search-the-web.md) - A `websearch` tool over Cloudflare's Web Search API for the pi harness, the AI SDK, and TanStack AI
|
|
146
146
|
- [Fetch the Web (Beta)](./fetch-the-web.md) - A `web_fetch` tool that reads a URL as Markdown, JSON, or text, with a host-controlled URL policy, for the pi harness, the AI SDK, TanStack AI, and Think
|
|
147
147
|
- TODO: [Cloudflare Sandboxes](./sandboxes.md) - Isolated environments for coding agents, ffmpeg, and heavy compute
|
package/docs/mcp-client.md
CHANGED
|
@@ -60,9 +60,11 @@ available.
|
|
|
60
60
|
Install the exact MCP client peer used by this Agents release:
|
|
61
61
|
|
|
62
62
|
```sh
|
|
63
|
-
pnpm add agents @modelcontextprotocol/client@2.
|
|
63
|
+
pnpm add agents @modelcontextprotocol/client@2.4.0
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
The MCP client does not need `@modelcontextprotocol/sdk` or `@modelcontextprotocol/server`. Those packages are optional peers used only by the MCP server APIs.
|
|
67
|
+
|
|
66
68
|
```typescript
|
|
67
69
|
import { Agent } from "agents";
|
|
68
70
|
|
|
@@ -365,6 +367,28 @@ class MyAgent extends Agent {
|
|
|
365
367
|
}
|
|
366
368
|
```
|
|
367
369
|
|
|
370
|
+
#### Client ID Metadata Documents
|
|
371
|
+
|
|
372
|
+
Some authorization servers accept a [Client ID Metadata Document](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization#client-id-metadata-documents) instead of dynamic client registration. Pass `clientMetadataUrl` to use one. When a server advertises `client_id_metadata_document_supported`, the agent sends that URL as its `client_id`. Servers that don't advertise it still get dynamic client registration.
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { Agent, DurableObjectOAuthClientProvider } from "agents";
|
|
376
|
+
import type { AgentMcpOAuthProvider } from "agents";
|
|
377
|
+
|
|
378
|
+
class MyAgent extends Agent {
|
|
379
|
+
createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {
|
|
380
|
+
return new DurableObjectOAuthClientProvider(
|
|
381
|
+
this.ctx.storage,
|
|
382
|
+
this.name,
|
|
383
|
+
callbackUrl,
|
|
384
|
+
{ clientMetadataUrl: "https://my-app.example.com/oauth/client.json" }
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Serve the document at that URL. `provider.clientMetadataDocument` returns its JSON: `client_id` is the URL and `redirect_uris` holds the callback URL. The authorization server checks every redirect URI against the document, so pass a fixed `callbackPath` to `addMcpServer` rather than relying on the per-instance default.
|
|
391
|
+
|
|
368
392
|
## Using MCP Capabilities
|
|
369
393
|
|
|
370
394
|
Once connected, access the server's capabilities:
|
package/docs/mcp-servers.md
CHANGED
|
@@ -5,10 +5,12 @@ Build an MCP server on Workers with `createMcpHandler` from `agents/mcp/server`
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
pnpm add agents @modelcontextprotocol/server@2.
|
|
8
|
+
pnpm add agents @modelcontextprotocol/server@2.4.0 zod
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Use the exact
|
|
11
|
+
`@modelcontextprotocol/server` is an optional peer dependency of `agents`, so your package manager does not install it for you. Use the exact version required by your installed Agents release.
|
|
12
|
+
|
|
13
|
+
Upgrading a server that uses `McpAgent`? See [Upgrading an existing `McpAgent` server](#upgrading-an-existing-mcpagent-server).
|
|
12
14
|
|
|
13
15
|
## Create a server
|
|
14
16
|
|
|
@@ -150,6 +152,7 @@ Wrap the handler with `OAuthProvider` from `@cloudflare/workers-oauth-provider`
|
|
|
150
152
|
```typescript
|
|
151
153
|
import { OAuthProvider } from "@cloudflare/workers-oauth-provider";
|
|
152
154
|
import { createMcpHandler, getMcpAuthContext } from "agents/mcp/server";
|
|
155
|
+
import { env } from "cloudflare:workers";
|
|
153
156
|
|
|
154
157
|
function createServer() {
|
|
155
158
|
const server = new McpServer({ name: "Authenticated", version: "1.0.0" });
|
|
@@ -189,15 +192,17 @@ export default new OAuthProvider({
|
|
|
189
192
|
return mcpHandler(request, env, ctx);
|
|
190
193
|
}
|
|
191
194
|
},
|
|
192
|
-
defaultHandler: AuthHandler // your consent and login flow
|
|
195
|
+
defaultHandler: AuthHandler, // your consent and login flow
|
|
196
|
+
// The URL MCP clients connect to. Every token is bound to it.
|
|
197
|
+
resourceMetadata: { resource: env.MCP_RESOURCE }
|
|
193
198
|
});
|
|
194
199
|
```
|
|
195
200
|
|
|
196
201
|
`OAuthProvider` needs an object with a `fetch` method, so wrap the handler as shown. Passing the handler function directly throws at startup.
|
|
197
202
|
|
|
198
|
-
`getMcpAuthContext().props` returns the `props` you passed to `completeAuthorization()` in your auth flow. Tool callbacks also receive the standard SDK v2 `AuthInfo` at `context.http.authInfo`. Do not log or return `context.http.authInfo.token` or `authInfo.extra.props`.
|
|
203
|
+
`getMcpAuthContext().props` returns the `props` you passed to `completeAuthorization()` in your auth flow. Tool callbacks also receive the standard SDK v2 `AuthInfo` at `context.http.authInfo`. `authInfo` is set only when the token has a client ID and `props` is a plain object. Tokens from `resolveExternalToken` have no client ID, so for those only `getMcpAuthContext().props` is available. Do not log or return `context.http.authInfo.token` or `authInfo.extra.props`.
|
|
199
204
|
|
|
200
|
-
The OAuth flow needs a KV namespace bound as `OAUTH_KV`. For a complete server with a login page, see [`examples/mcp-worker-authenticated`](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). For consent
|
|
205
|
+
Set `MCP_RESOURCE` in `wrangler.jsonc` to the URL clients connect to: Workers OAuth Provider 1.x binds every token to it. The OAuth flow also needs a KV namespace bound as `OAUTH_KV`. For a complete server with a login page, see [`examples/mcp-worker-authenticated`](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker-authenticated). For the consent page and signing in through a third-party provider, see [Securing MCP Servers](./securing-mcp-servers.md).
|
|
201
206
|
|
|
202
207
|
## Elicitation
|
|
203
208
|
|
|
@@ -269,9 +274,23 @@ The handler does not serve the standalone SSE transport.
|
|
|
269
274
|
|
|
270
275
|
If the handler lifecycle does not fit, use the SDK's `WebStandardStreamableHTTPServerTransport` from `@modelcontextprotocol/server` directly in your Worker.
|
|
271
276
|
|
|
272
|
-
##
|
|
277
|
+
## Upgrading an existing `McpAgent` server
|
|
278
|
+
|
|
279
|
+
`McpAgent` is deprecated, but existing servers keep working. It is built on MCP SDK v1, which is an optional peer dependency of `agents`, so your package manager no longer installs it for you. Add the exact version your Agents release expects before you upgrade:
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
pnpm add agents @modelcontextprotocol/sdk@1.32.2 zod
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Keep importing `McpServer` from `@modelcontextprotocol/sdk/server/mcp.js` in an `McpAgent`. An SDK v2 server from `@modelcontextprotocol/server` cannot run inside `McpAgent`. The same applies to `WorkerTransport` and `createLegacyMcpHandler` from `agents/mcp`.
|
|
286
|
+
|
|
287
|
+
`agents/x402` also needs `@modelcontextprotocol/sdk`. It does not load the package at runtime, but its types refer to SDK v1 clients and tools.
|
|
288
|
+
|
|
289
|
+
If your server imported `@modelcontextprotocol/sdk` without listing it in `package.json`, it only worked because `agents` installed the package. After you upgrade, the build fails with an unresolved `@modelcontextprotocol/sdk` import until you add it.
|
|
290
|
+
|
|
291
|
+
Client code does not need the v1 SDK. If you import client helpers such as `RPCClientTransport` or `normalizeServerId` from `agents/mcp`, import them from `agents/mcp/client` instead.
|
|
273
292
|
|
|
274
|
-
|
|
293
|
+
To move the server itself to `createMcpHandler`, follow [Migrate to MCP SDK v2](https://developers.cloudflare.com/agents/model-context-protocol/guides/migrate-to-mcp-sdk-v2/).
|
|
275
294
|
|
|
276
295
|
## Examples
|
|
277
296
|
|
package/docs/models-pi-ai.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Models for pi-ai
|
|
1
|
+
# Models for pi-ai
|
|
2
2
|
|
|
3
3
|
`agents/models/pi-ai` is the [pi-ai](https://github.com/earendil-works/pi/tree/main/packages/ai)
|
|
4
4
|
twin of [`agents/models/ai-sdk`](./models.md): the same `createAI` factory, the same options,
|
|
@@ -21,7 +21,7 @@ import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
|
21
21
|
|
|
22
22
|
const ai = createAI({ binding: env.AI, id: "prod", cacheTtl: 60 });
|
|
23
23
|
|
|
24
|
-
ai("@cf/zai-org/glm-
|
|
24
|
+
ai("@cf/zai-org/glm-5.3-flash"); // Workers AI: our catalog, our compat layer
|
|
25
25
|
ai(getBuiltinModel("anthropic", "claude-opus-4-8")); // their model, our transport
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -47,7 +47,6 @@ design: a model this package cannot name exactly is yours to construct.
|
|
|
47
47
|
`env.AI.run`, other model objects through the binding's `fetch` to AI Gateway's
|
|
48
48
|
provider-native path. With [an account id and API token](#account-id-and-api-token) the
|
|
49
49
|
same requests go over HTTP instead.
|
|
50
|
-
5. Everything here is in beta and may change in a minor release.
|
|
51
50
|
|
|
52
51
|
## Quick start
|
|
53
52
|
|
|
@@ -66,7 +65,7 @@ import { createAI } from "agents/models/pi-ai";
|
|
|
66
65
|
export default {
|
|
67
66
|
async fetch(_request: Request, env: { AI: Ai }) {
|
|
68
67
|
const ai = createAI({ binding: env.AI });
|
|
69
|
-
const reply = await ai.complete(ai("@cf/zai-org/glm-
|
|
68
|
+
const reply = await ai.complete(ai("@cf/zai-org/glm-5.3-flash"), {
|
|
70
69
|
messages: [{ role: "user", content: "Hello", timestamp: Date.now() }]
|
|
71
70
|
});
|
|
72
71
|
// `content` is an array of parts — text, thinking, tool calls.
|
|
@@ -103,7 +102,7 @@ Workers AI and catalog models go to AI Gateway's
|
|
|
103
102
|
|
|
104
103
|
```ts
|
|
105
104
|
// 1. Workers AI — ours.
|
|
106
|
-
ai("@cf/zai-org/glm-
|
|
105
|
+
ai("@cf/zai-org/glm-5.3-flash");
|
|
107
106
|
|
|
108
107
|
// 2. pi-ai's Cloudflare AI Gateway catalog — a string, resolved by pi, not us.
|
|
109
108
|
ai("anthropic/claude-opus-4.8");
|
|
@@ -181,7 +180,7 @@ import { createModels } from "@earendil-works/pi-ai/models";
|
|
|
181
180
|
const models = createModels();
|
|
182
181
|
models.setProvider(ai.provider); // provider id: "cloudflare"
|
|
183
182
|
models.getModel("cloudflare", "anthropic/claude-opus-4.8");
|
|
184
|
-
models.streamSimple(ai("@cf/zai-org/glm-
|
|
183
|
+
models.streamSimple(ai("@cf/zai-org/glm-5.3-flash"), context);
|
|
185
184
|
```
|
|
186
185
|
|
|
187
186
|
The provider's static list is every Workers AI id pi-ai knows plus every `<provider>/<id>` in
|
|
@@ -206,7 +205,7 @@ ai("anthropic/claude-opus-4.8", {
|
|
|
206
205
|
requestTimeoutMs: 30_000,
|
|
207
206
|
retries: { maxAttempts: 3, backoff: "exponential", retryDelayMs: 500 },
|
|
208
207
|
byokAlias: "team-a", // which stored BYOK key, by alias
|
|
209
|
-
fallback: ["@cf/zai-org/glm-
|
|
208
|
+
fallback: ["@cf/zai-org/glm-5.3-flash"], // ids or models, in any mix
|
|
210
209
|
headers: { "x-request-source": "docs" },
|
|
211
210
|
sessionAffinity: "chat-42", // Workers AI prefix-cache routing
|
|
212
211
|
reasoningEffort: "low", // "low" | "medium" | "high" | null
|
|
@@ -336,7 +335,7 @@ and are not resumed. The run id is on the `cloudflare` diagnostic as `runId`.
|
|
|
336
335
|
## Fallback
|
|
337
336
|
|
|
338
337
|
```ts
|
|
339
|
-
ai(claude, { fallback: ["@cf/zai-org/glm-
|
|
338
|
+
ai(claude, { fallback: ["@cf/zai-org/glm-5.3-flash"] });
|
|
340
339
|
```
|
|
341
340
|
|
|
342
341
|
Legs may be Workers AI ids or models, in any mix. They are tried in order: a leg is abandoned
|
|
@@ -368,11 +367,10 @@ Image generation is Workers AI only. The knobs a model takes are the model's:
|
|
|
368
367
|
in a `cloudflare-compat` diagnostic on the result rather than sent and ignored.
|
|
369
368
|
Every other model in the catalog takes the full set.
|
|
370
369
|
|
|
371
|
-
##
|
|
370
|
+
## Requirements
|
|
372
371
|
|
|
373
372
|
This subpath needs `@earendil-works/pi-ai@~1.4.0`, an optional peer of `agents`. `agents`
|
|
374
|
-
takes no vendor package as a dependency, optional or otherwise.
|
|
375
|
-
and may change in a minor release. An unlisted `@cf/` id resolves with default metadata (a
|
|
373
|
+
takes no vendor package as a dependency, optional or otherwise. An unlisted `@cf/` id resolves with default metadata (a
|
|
376
374
|
128k context window, 8192 output tokens, zero cost); pass overrides when you know better.
|
|
377
375
|
|
|
378
376
|
## See also
|
package/docs/models.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Models
|
|
1
|
+
# Models
|
|
2
2
|
|
|
3
3
|
`agents/models/ai-sdk` is Cloudflare's AI SDK provider. It takes two call
|
|
4
4
|
forms, through the `AI` binding or
|
|
@@ -557,13 +557,6 @@ try {
|
|
|
557
557
|
On a model object this covers the gateway's own failures; a vendor's own error
|
|
558
558
|
is raised by that vendor's provider in its own error type.
|
|
559
559
|
|
|
560
|
-
## Experimental
|
|
561
|
-
|
|
562
|
-
This module is experimental. The surface may change in a minor release, and
|
|
563
|
-
every exported symbol is tagged `@experimental`. It ships from `agents` first;
|
|
564
|
-
the plan is for `cloudflare/ai` to re-export it and deprecate the older
|
|
565
|
-
`workers-ai-provider` / `ai-gateway-provider` packages.
|
|
566
|
-
|
|
567
560
|
## See also
|
|
568
561
|
|
|
569
562
|
- [Models for pi-ai](./models-pi-ai.md) — the same factory for pi-ai and pi-durable
|
package/docs/observability.md
CHANGED
|
@@ -438,9 +438,11 @@ exists:
|
|
|
438
438
|
`gen_ai.response.finish_reasons` and `gen_ai.request.stop_sequences` are arrays
|
|
439
439
|
in OTel. Workers' custom `Span.setAttribute` currently accepts only a string,
|
|
440
440
|
number, or boolean, so the wrapper omits those attributes rather than placing
|
|
441
|
-
JSON text under an array-typed key.
|
|
442
|
-
|
|
443
|
-
`
|
|
441
|
+
JSON text under an array-typed key. Failures emit `error.type` and, on runtimes
|
|
442
|
+
with `Span.setStatus()` (the 2026-10-26 release or later), set span status
|
|
443
|
+
`error` without a description. Status is span state, exported to OpenTelemetry
|
|
444
|
+
destinations, not an attribute; the raw error message is never recorded.
|
|
445
|
+
Cancellations leave the status unset.
|
|
444
446
|
|
|
445
447
|
### Context and safety
|
|
446
448
|
|