@ax-llm/ax 23.0.1 → 23.0.2
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/index.cjs +542 -520
- package/index.cjs.map +1 -1
- package/index.d.cts +7919 -5853
- package/index.d.ts +7919 -5853
- package/index.global.js +542 -520
- package/index.global.js.map +1 -1
- package/index.js +542 -520
- package/index.js.map +1 -1
- package/package.json +1 -4
- package/skills/ax-agent-context.md +1 -1
- package/skills/ax-agent-memory-skills.md +1 -1
- package/skills/ax-agent-observability.md +1 -1
- package/skills/ax-agent-optimize.md +9 -2
- package/skills/ax-agent-rlm.md +1 -1
- package/skills/ax-agent.md +70 -19
- package/skills/ax-ai.md +17 -6
- package/skills/ax-audio.md +1 -1
- package/skills/ax-event-runtime.md +145 -0
- package/skills/ax-flow.md +241 -1
- package/skills/ax-gen.md +50 -2
- package/skills/ax-gepa.md +1 -1
- package/skills/ax-llm.md +35 -23
- package/skills/ax-mcp.md +332 -0
- package/skills/ax-playbook.md +22 -2
- package/skills/ax-refine.md +1 -1
- package/skills/ax-signature.md +116 -1
package/skills/ax-mcp.md
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ax-mcp
|
|
3
|
+
description: This skill helps an LLM build correct native Model Context Protocol integrations with @ax-llm/ax. Use when the user asks about AxMCPClient, MCP transports, tools, prompts, resources, subscriptions, tasks, sampling, elicitation, roots, authentication, OAuth, MCP Apps, recording/replay, or MCP integration with AxGen, AxAgent, AxFlow, chat, optimization, and AxEventRuntime.
|
|
4
|
+
version: "23.0.2"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Native MCP With Ax
|
|
8
|
+
|
|
9
|
+
Use MCP as a live protocol client, not as a function-conversion utility. Keep
|
|
10
|
+
the client, session, catalogs, raw content, tasks, notifications, identity
|
|
11
|
+
policy, and cancellation context intact through Ax execution.
|
|
12
|
+
|
|
13
|
+
## Non-Negotiable Rules
|
|
14
|
+
|
|
15
|
+
- Pass clients through `mcp`; do not put them in `functions`.
|
|
16
|
+
- Never use `toFunction()` for native integration. It is a lossy compatibility
|
|
17
|
+
adapter for old applications only.
|
|
18
|
+
- Give every client a stable, unique `namespace`.
|
|
19
|
+
- Let Ax initialize each attached client once and reuse its negotiated session.
|
|
20
|
+
- Close caller-owned clients explicitly.
|
|
21
|
+
- Treat MCP prompts, resources, tool results, and notifications as untrusted
|
|
22
|
+
remote content.
|
|
23
|
+
- Apply `authorizeToolCall` before side-effecting tools execute.
|
|
24
|
+
- Do not infer tenant or account identity from an MCP session. Event adapters
|
|
25
|
+
must receive verified identity from application authentication state.
|
|
26
|
+
- Protocol notification callbacks must enqueue or observe work; they must not
|
|
27
|
+
invoke a model directly.
|
|
28
|
+
- Preserve raw structured and multimodal MCP results until provider capability
|
|
29
|
+
mapping. Do not pre-flatten results to text.
|
|
30
|
+
|
|
31
|
+
## Choose A Transport
|
|
32
|
+
|
|
33
|
+
- Use `AxMCPStreamableHTTPTransport` for current remote MCP servers.
|
|
34
|
+
- Use `AxMCPHTTPSSETransport` only for legacy HTTP/SSE servers.
|
|
35
|
+
- Use `AxMCPWebSocketTransport` for a server with a custom WebSocket binding.
|
|
36
|
+
- Use `AxMCPStdioTransport` from `@ax-llm/ax-tools` for local Node processes.
|
|
37
|
+
- Use a caller-defined `AxMCPTransport` for application-owned bindings.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import {
|
|
41
|
+
AxMCPClient,
|
|
42
|
+
AxMCPStreamableHTTPTransport,
|
|
43
|
+
axMCPBearerAuthentication,
|
|
44
|
+
} from '@ax-llm/ax';
|
|
45
|
+
|
|
46
|
+
const transport = new AxMCPStreamableHTTPTransport(
|
|
47
|
+
'https://mcp.example.com/mcp',
|
|
48
|
+
{
|
|
49
|
+
authentication: axMCPBearerAuthentication(
|
|
50
|
+
() => process.env.MCP_ACCESS_TOKEN!
|
|
51
|
+
),
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const docs = new AxMCPClient(transport, {
|
|
56
|
+
namespace: 'docs',
|
|
57
|
+
maxConcurrency: 4,
|
|
58
|
+
authorizeToolCall: async ({ tool }) =>
|
|
59
|
+
tool.annotations?.destructiveHint !== true,
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For local stdio:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { AxMCPClient } from '@ax-llm/ax';
|
|
67
|
+
import { AxMCPStdioTransport } from '@ax-llm/ax-tools';
|
|
68
|
+
|
|
69
|
+
const stdio = new AxMCPStdioTransport({
|
|
70
|
+
command: 'node',
|
|
71
|
+
args: ['./server.mjs'],
|
|
72
|
+
});
|
|
73
|
+
const local = new AxMCPClient(stdio, { namespace: 'local' });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`AxMCPStdioTransport` owns its child process. After `local.close()`, also call
|
|
77
|
+
`stdio.terminate()` until the stdio transport exposes the common `close()`
|
|
78
|
+
lifecycle directly.
|
|
79
|
+
|
|
80
|
+
## Attach MCP To AxGen
|
|
81
|
+
|
|
82
|
+
Attach clients in constructor or forward options. Per-call options override
|
|
83
|
+
instance defaults.
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
const gen = ax('question:string -> answer:string', { mcp: docs });
|
|
87
|
+
|
|
88
|
+
const result = await gen.forward(llm, { question }, {
|
|
89
|
+
mcpContext: [
|
|
90
|
+
{ client: 'docs', resource: { uri: 'docs://guide' } },
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`mcpContext` resolves selected prompts or resources before the first model
|
|
96
|
+
call and adds attributed, untrusted context. Native tool calls retain client
|
|
97
|
+
identity and raw MCP results in memory. `streamingForward()` keeps Ax output
|
|
98
|
+
streaming separate from MCP progress and task events.
|
|
99
|
+
|
|
100
|
+
## Attach MCP To AxAgent
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const assistant = agent('query:string -> answer:string', {
|
|
104
|
+
mcp: [docs, search],
|
|
105
|
+
mcpInheritance: 'all',
|
|
106
|
+
functionDiscovery: true,
|
|
107
|
+
contextFields: [],
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Agents expose native modules under `mcp.<namespace>`:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
mcp.docs.tools.<tool>
|
|
115
|
+
mcp.docs.prompts.list()
|
|
116
|
+
mcp.docs.prompts.get(name, args)
|
|
117
|
+
mcp.docs.resources.list()
|
|
118
|
+
mcp.docs.resources.templates()
|
|
119
|
+
mcp.docs.resources.read(uri)
|
|
120
|
+
mcp.docs.resources.subscribe(uri)
|
|
121
|
+
mcp.docs.resources.unsubscribe(uri)
|
|
122
|
+
mcp.docs.tasks.list()
|
|
123
|
+
mcp.docs.tasks.get(taskId)
|
|
124
|
+
mcp.docs.tasks.result(taskId)
|
|
125
|
+
mcp.docs.tasks.cancel(taskId)
|
|
126
|
+
mcp.docs.complete(...)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Use `mcpInheritance: 'all'`, `'none'`, or a namespace allowlist. The resulting
|
|
130
|
+
live execution context propagates through Agent stages, `llmQuery`, RLM, and
|
|
131
|
+
child programs. Large catalogs participate in Agent discovery; do not copy
|
|
132
|
+
their tools into an inline `functions` array.
|
|
133
|
+
|
|
134
|
+
## AxFlow And High-Level Chat
|
|
135
|
+
|
|
136
|
+
Pass `mcp` in Flow defaults or forward options. Nested nodes inherit the same
|
|
137
|
+
execution context unless `mcpInheritance` restricts it. Parallel nodes share
|
|
138
|
+
the client while respecting its concurrency limit and abort signal.
|
|
139
|
+
|
|
140
|
+
Use `axMCPChat(ai, request, { mcp })` for a high-level non-streaming native MCP
|
|
141
|
+
tool loop. Do not build a second ad-hoc tool dispatcher around `ai.chat()`.
|
|
142
|
+
|
|
143
|
+
## Catalogs And Raw Operations
|
|
144
|
+
|
|
145
|
+
An endpoint is only the server address. The server owns tool names, prompt
|
|
146
|
+
names, resource names, resource URIs, and URI templates. Discover one cloned
|
|
147
|
+
snapshot before asking users to configure identifiers:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const catalog = await docs.inspectCatalog();
|
|
151
|
+
|
|
152
|
+
console.log(catalog.tools);
|
|
153
|
+
console.log(catalog.prompts);
|
|
154
|
+
console.log(catalog.resources);
|
|
155
|
+
console.log(catalog.resourceTemplates);
|
|
156
|
+
|
|
157
|
+
const prompt = await docs.getPrompt('review', { topic: 'MCP' });
|
|
158
|
+
const resource = await docs.readResource('docs://guide');
|
|
159
|
+
const completion = await docs.complete(reference, argument);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`inspectCatalog({ refresh: true })` forces fresh bounded pagination. Snapshot
|
|
163
|
+
mutation cannot change the live client. List-change notifications refresh the
|
|
164
|
+
catalog revision, and native Ax model steps rebuild tool definitions when that
|
|
165
|
+
revision changes. Concrete resources can be selected immediately. URI
|
|
166
|
+
templates are discoverable but never expanded automatically; applications
|
|
167
|
+
construct an authorized concrete URI and may use MCP completion to suggest
|
|
168
|
+
argument values.
|
|
169
|
+
|
|
170
|
+
## Tasks, Progress, And Cancellation
|
|
171
|
+
|
|
172
|
+
Use task-aware calls when the server advertises tasks:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const created = await docs.callToolTask('reindex', { scope: 'all' });
|
|
176
|
+
const task = await docs.getTask(created.task.taskId);
|
|
177
|
+
await docs.cancelTask(task.taskId);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Use `subscribeTaskStatus` or `subscribeEvents` for observation. Keep polling
|
|
181
|
+
available because task notifications are optional. Pass Ax abort signals
|
|
182
|
+
through program execution; never blindly replay a tool call after an uncertain
|
|
183
|
+
post-side-effect failure.
|
|
184
|
+
|
|
185
|
+
## Subscriptions And Event-Driven Agents
|
|
186
|
+
|
|
187
|
+
Use `AxMCPEventSource` with `AxEventRuntime`. A subscription callback only
|
|
188
|
+
publishes an event into the inbox. Explicit routes decide whether to observe,
|
|
189
|
+
invalidate, wake, or resume.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const source = new AxMCPEventSource({
|
|
193
|
+
client: docs,
|
|
194
|
+
resourceSubscriptions: {
|
|
195
|
+
select: (resource) =>
|
|
196
|
+
resource.mimeType === 'text/markdown' &&
|
|
197
|
+
resource.name === 'Engineering guide',
|
|
198
|
+
},
|
|
199
|
+
identity: { tenantId: 'tenant-1' },
|
|
200
|
+
trust: 'authenticated',
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const runtime = eventRuntime({
|
|
204
|
+
allowVolatile: true,
|
|
205
|
+
sources: [source],
|
|
206
|
+
routes: [
|
|
207
|
+
...axMCPEventRoutes({ client: docs }),
|
|
208
|
+
eventRoute('guide-updated')
|
|
209
|
+
.types('mcp.resource.updated')
|
|
210
|
+
.authenticated()
|
|
211
|
+
.wake(
|
|
212
|
+
eventTarget('reviewer')
|
|
213
|
+
.program(reviewer)
|
|
214
|
+
.ai(llm)
|
|
215
|
+
.input((input) =>
|
|
216
|
+
input.field('uri', eventPath.data('uri'))
|
|
217
|
+
)
|
|
218
|
+
.build()
|
|
219
|
+
)
|
|
220
|
+
.build(),
|
|
221
|
+
],
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Safe defaults are:
|
|
226
|
+
|
|
227
|
+
- omitted resource policy -> subscribe to no resources
|
|
228
|
+
- `'all'` -> explicitly subscribe to all discovered concrete resources
|
|
229
|
+
- URI array -> explicitly subscribe to application-constructed concrete URIs
|
|
230
|
+
- selector -> choose concrete resources by name, URI, description, MIME type,
|
|
231
|
+
annotations, or the surrounding catalog
|
|
232
|
+
- catalog changes -> `invalidate`
|
|
233
|
+
- progress and logging -> `observe`
|
|
234
|
+
- resource updates -> no implicit wake
|
|
235
|
+
- `input_required` and terminal task states -> resume the owning continuation
|
|
236
|
+
|
|
237
|
+
The signature-aware input plan is the data boundary. Raw event data remains in
|
|
238
|
+
`eventContext`; only fields selected with segment-safe `eventPath` descriptors
|
|
239
|
+
become program inputs. Use multiple matching routes to fan one notification out
|
|
240
|
+
to multiple Agents with independent authorization and run records.
|
|
241
|
+
|
|
242
|
+
Managed sources refresh and diff their selection after
|
|
243
|
+
`notifications/resources/list_changed`. They keep the prior selection if a
|
|
244
|
+
selector throws, retain successful wire transitions after a partial failure,
|
|
245
|
+
and retry incomplete work on the next change or reconnect. The client tracks a
|
|
246
|
+
separate logical owner for manual subscriptions, every source, and restored
|
|
247
|
+
intent: only the first owner sends `resources/subscribe`, and only the last
|
|
248
|
+
release sends `resources/unsubscribe`. Closing a source cannot break another
|
|
249
|
+
owner. Closing the client terminates all ownership and transport state.
|
|
250
|
+
|
|
251
|
+
For the detailed lifecycle and troubleshooting guide, read
|
|
252
|
+
`docs/MCP_SUBSCRIPTIONS.md` and use the checked-in six-language MCP examples.
|
|
253
|
+
|
|
254
|
+
## Server-Initiated Requests
|
|
255
|
+
|
|
256
|
+
Configure handlers on `AxMCPClient` when advertising the corresponding client
|
|
257
|
+
capability:
|
|
258
|
+
|
|
259
|
+
- `sampling` for `sampling/createMessage`
|
|
260
|
+
- `elicitation` for form or URL elicitation
|
|
261
|
+
- `roots` for `roots/list`
|
|
262
|
+
- `onProgress`, `onLoggingMessage`, and `onTaskStatus` for observation
|
|
263
|
+
|
|
264
|
+
Do not advertise a client capability without a working host handler and policy.
|
|
265
|
+
|
|
266
|
+
## Authentication And OAuth
|
|
267
|
+
|
|
268
|
+
For simple authentication, compose `axMCPBearerAuthentication`,
|
|
269
|
+
`axMCPBasicAuthentication`, `axMCPAPIKeyAuthentication`,
|
|
270
|
+
`axMCPHMACAuthentication`, or a caller-defined strategy in the HTTP transport.
|
|
271
|
+
|
|
272
|
+
Use the transport `oauth` option for protected-resource discovery, PKCE,
|
|
273
|
+
client metadata or dynamic registration, refresh, challenge-driven scope
|
|
274
|
+
step-up, DPoP, PAR/JAR/RAR, mTLS, revocation, introspection, client credentials,
|
|
275
|
+
or enterprise-managed authorization. Supply persistent token and registration
|
|
276
|
+
stores in distributed deployments. Never serialize tokens into Ax program or
|
|
277
|
+
event state.
|
|
278
|
+
|
|
279
|
+
Keep SSRF protection enabled for remote discovery and redirect handling. Relax
|
|
280
|
+
loopback or HTTP restrictions only for controlled local development.
|
|
281
|
+
|
|
282
|
+
For checked-in Streamable HTTP examples, set `AX_MCP_ENDPOINT`. A localhost
|
|
283
|
+
TypeScript demo must opt in explicitly with
|
|
284
|
+
`ssrfProtection: { allowHTTP: true, allowLoopback: true }`; never copy that
|
|
285
|
+
configuration to a remote endpoint. Generated examples use their equivalent
|
|
286
|
+
`requireHttps` / `allowLocalhost` / `allowPrivateNetworks` fields only for
|
|
287
|
+
`127.0.0.1`.
|
|
288
|
+
|
|
289
|
+
For a real local check, run `src/examples/mcp-event-demo-server.ts`, set
|
|
290
|
+
`AX_MCP_ENDPOINT=http://127.0.0.1:3001/mcp`, and trigger
|
|
291
|
+
`/control/resource` or `/control/task/complete`. The mandatory credential-free
|
|
292
|
+
matrix is `npm run test:mcp-events:generated`; provider-backed examples are
|
|
293
|
+
advisory and require their documented API key.
|
|
294
|
+
|
|
295
|
+
## MCP Apps And Extensions
|
|
296
|
+
|
|
297
|
+
Negotiate official extensions through client capabilities. Use
|
|
298
|
+
`AxMCPAppBridge` for MCP App resources and host messages; enforce CSP,
|
|
299
|
+
permissions, visibility, allowed tools, and untrusted model-context policy.
|
|
300
|
+
Do not render arbitrary HTML returned from a normal tool result as an MCP App.
|
|
301
|
+
|
|
302
|
+
## Recording, Replay, And Evaluation
|
|
303
|
+
|
|
304
|
+
Wrap a real transport with `AxMCPRecordingTransport` to capture deterministic
|
|
305
|
+
protocol interactions. Use `AxMCPReplayTransport` for tests, optimization, and
|
|
306
|
+
evaluation. Live MCP evaluation is rejected by default because repeated model
|
|
307
|
+
runs could repeat external side effects; opt in only deliberately.
|
|
308
|
+
|
|
309
|
+
## Testing Checklist
|
|
310
|
+
|
|
311
|
+
- Use a local deterministic protocol server or replay transport.
|
|
312
|
+
- Assert namespace and tool collisions fail before model execution.
|
|
313
|
+
- Test raw text, image, audio, resource-link, embedded-resource, metadata,
|
|
314
|
+
task, and error results.
|
|
315
|
+
- Test catalog changes during a multi-step run.
|
|
316
|
+
- Test authorization denial before transport execution.
|
|
317
|
+
- Test subscription reconnect and logical resubscription.
|
|
318
|
+
- Test anonymous events cannot match authenticated routes.
|
|
319
|
+
- Test terminal task events resume only the owning identity and correlation.
|
|
320
|
+
- Test cancellation and uncertain outcomes without duplicate side effects.
|
|
321
|
+
- Close clients, listening handles, runtimes, and local servers in `finally`.
|
|
322
|
+
|
|
323
|
+
Generated transports supervise real long-lived GET/SSE connections and resume
|
|
324
|
+
with `Last-Event-ID` when available. Generated event runtimes remain
|
|
325
|
+
host-driven: schedule delayed work with `nextDueAt()` and `runDue()`. Rust hosts
|
|
326
|
+
also call `AxMCPEventSource.poll()` to drain protocol callbacks on the host
|
|
327
|
+
thread. Close the source/runtime before the caller-owned client so unsubscribe
|
|
328
|
+
and cancellation messages can still be sent.
|
|
329
|
+
|
|
330
|
+
For generic inbox, continuation, store, and sink behavior, use the
|
|
331
|
+
`ax-event-runtime` skill. For program-specific behavior, combine this skill with
|
|
332
|
+
`ax-gen`, `ax-agent`, or `ax-flow`.
|
package/skills/ax-playbook.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ax-playbook
|
|
3
3
|
description: This skill helps an LLM generate correct playbook code using @ax-llm/ax. Use when the user asks about playbook(), AxPlaybook, context playbooks, evolving context, ACE / Agentic Context Engineering, agent.playbook(), or growing/applying task knowledge offline and online with evolve() and update().
|
|
4
|
-
version: "23.0.
|
|
4
|
+
version: "23.0.2"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Playbook Codegen Rules (@ax-llm/ax)
|
|
@@ -29,7 +29,10 @@ Use this skill to generate context-playbook code. A playbook grows an evolving b
|
|
|
29
29
|
- `applyTo()` injects a `## Context Playbook` block into the program description; calling it repeatedly recomposes from the original base (no stacking).
|
|
30
30
|
- Keep the offline `metric` deterministic and cheap, like a GEPA metric.
|
|
31
31
|
- A playbook is plain JSON. Persist `pb.toJSON()` and `load(...)` it into a fresh program for production.
|
|
32
|
-
-
|
|
32
|
+
- The playbook engine, construction-time agent attachment, failure harvesting,
|
|
33
|
+
and verified agent evolution are available in TypeScript and the generated
|
|
34
|
+
Python, Java, C++, Go, and Rust packages. Use each package's native casing and
|
|
35
|
+
callback types.
|
|
33
36
|
|
|
34
37
|
## Offline Pattern (evolve)
|
|
35
38
|
|
|
@@ -86,6 +89,23 @@ const result = await apb.evolve(
|
|
|
86
89
|
|
|
87
90
|
The agent-level `evolve(dataset, options)` is distinct from the program-level `pb.evolve(examples, metric)` above: it takes an `AxAgentEvalDataset` plus options, runs the whole pipeline, and returns baseline/final held-in & held-out with per-bullet outcomes (no `{ bestScore }`). For full-pipeline tuning of agent instructions and demos (not the playbook) use `agent.optimize(...)` (GEPA).
|
|
88
91
|
|
|
92
|
+
Generated packages expose that same agent-bound loop with language-shaped APIs:
|
|
93
|
+
|
|
94
|
+
| Language | Agent-bound evolve call |
|
|
95
|
+
|---|---|
|
|
96
|
+
| Python | `agent.playbook().evolve(dataset, options)` |
|
|
97
|
+
| Java | `agent.playbook(null).evolve(dataset, options)` |
|
|
98
|
+
| C++ | `agent.get_playbook()->evolve(dataset, options)` |
|
|
99
|
+
| Go | `agent.GetPlaybook().EvolveAgent(ctx, dataset, options)` |
|
|
100
|
+
| Rust | `playbook.evolve_agent(&mut agent, client, dataset, options)` |
|
|
101
|
+
|
|
102
|
+
All five generated packages thread structured `failureSignals` through agent
|
|
103
|
+
evaluation predictions. The default verify gate accepts a proposed bullet only
|
|
104
|
+
when held-in score improves and held-out score stays within `epsilon`; rejection
|
|
105
|
+
restores the exact prior snapshot. Scoring is host-shaped: TypeScript uses its
|
|
106
|
+
metric, Python/Java/Go can accept a metric callback, and all generated ports can
|
|
107
|
+
use task `score`/`scores` values plus the agent evaluation result.
|
|
108
|
+
|
|
89
109
|
## Playbook vs optimize()
|
|
90
110
|
|
|
91
111
|
- `playbook(...)` — accumulate reusable, evolving task knowledge; the only path that also learns online via `update(...)`.
|
package/skills/ax-refine.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ax-refine
|
|
3
3
|
description: Use this skill when writing or reviewing Ax bestOfN/refine code, reward functions, thresholds, native sample selection, serial attempts, generated advice, and attempt diagnostics.
|
|
4
|
-
version: "23.0.
|
|
4
|
+
version: "23.0.2"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Ax Refine And BestOfN
|
package/skills/ax-signature.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ax-signature
|
|
3
3
|
description: This skill helps an LLM generate correct DSPy signature code using @ax-llm/ax. Use when the user asks about signatures, s(), f(), field types, string syntax, fluent builder API, validation constraints, or type-safe inputs/outputs.
|
|
4
|
-
version: "23.0.
|
|
4
|
+
version: "23.0.2"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Ax Signature Reference
|
|
@@ -41,6 +41,113 @@ Date, datetime, and range fields are AI-friendly but strict. They accept ISO-sty
|
|
|
41
41
|
'problem:string -> reasoning!:string, solution:string' // internal with !
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
## Extended String Grammar (Modifier Bags + Nested Objects)
|
|
45
|
+
|
|
46
|
+
The string form is constraint-complete: everything the fluent API expresses
|
|
47
|
+
(except Standard Schema fields) can be written in the string. A type takes an
|
|
48
|
+
optional comma-separated, order-free **modifier bag** in parentheses, and
|
|
49
|
+
objects declare structured fields inline.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
`userAge:number(min 0, max 120), contactEmail:string(format email, cache), codeSnippet:code(python)
|
|
53
|
+
-> userName:string(pattern "^[a-z_]+$" "lowercase name"), tagList:string(item "a short tag")[] "all tags",
|
|
54
|
+
profileList:object{ fullName:string, userAge?:number(min 0) }[] "matched profiles"`
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
| Modifier | Applies to | Effect |
|
|
58
|
+
|----------|-----------|--------|
|
|
59
|
+
| `min N` / `max N` | `string`, `number` | String length bounds / numeric value bounds |
|
|
60
|
+
| `format email\|uri\|date\|date-time` | `string` | Format validation |
|
|
61
|
+
| `pattern "regex" ["desc"]` | `string` | Regex validation with optional description |
|
|
62
|
+
| `cache` | top-level input | Prefix-cache breakpoint |
|
|
63
|
+
| `item "desc"` | arrays | Per-item description: `tags:string(item "a tag")[]` |
|
|
64
|
+
| `<language>` | `code` | Language of the snippet: `snippet:code(python)` |
|
|
65
|
+
|
|
66
|
+
- `object{ field:type, opt?:type }` nests recursively; append `[]` for an array of objects.
|
|
67
|
+
- Optional goes on the **name** (`userAge?:number`), never after the type.
|
|
68
|
+
- The string API is **strict**: a modifier that does not apply to its type (e.g. `min` on a boolean) is a parse error, where the fluent API silently ignores it.
|
|
69
|
+
- Inside `object{ ... }`, the `!` internal marker, media types, `cache`, and `item` are rejected (they only apply at the top level).
|
|
70
|
+
- In quoted values, backslashes are doubled — a regex `\d` is written `pattern "\\d+"`.
|
|
71
|
+
- `AxSignature.toString()` renders every construct back to this grammar losslessly, so a signature round-trips — this is what lets a whole flow serialize its node contracts into mermaid `%%ax` directives (see the ax-flow skill).
|
|
72
|
+
|
|
73
|
+
## Signature Gallery
|
|
74
|
+
|
|
75
|
+
Real-world contracts, one line each — every entry below parses with `s()` as written (`#` lines are captions, not part of the signature):
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
# Support triage: several class outputs plus a capped reply draft
|
|
79
|
+
ticketText:string -> priorityClass:class "p0, p1, p2", sentimentClass:class "angry, neutral, happy", replyDraft:string(max 500)
|
|
80
|
+
|
|
81
|
+
# Invoice extraction: regex-validated id, bounded totals, structured line items
|
|
82
|
+
invoiceText:string -> invoiceNumber:string(pattern "^INV-\\d+$" "INV- then digits"), totalAmount:number(min 0), lineItems:object{ description:string, quantity:number(min 1), unitPrice:number }[]
|
|
83
|
+
|
|
84
|
+
# Contact enrichment: optional format-validated outputs
|
|
85
|
+
bioText:string -> contactEmail?:string(format email), websiteUrl?:string(format uri), birthDate?:string(format date)
|
|
86
|
+
|
|
87
|
+
# RAG: cached corpus input plus per-item described citations
|
|
88
|
+
corpusText:string(cache), userQuestion:string -> answerText:string, citedChunks:string(item "verbatim quote")[]
|
|
89
|
+
|
|
90
|
+
# Code generation: language-tagged code outputs
|
|
91
|
+
taskBrief:string -> pythonScript:code(python), testCases:code(python), riskNotes?:string
|
|
92
|
+
|
|
93
|
+
# Chain of thought: internal reasoning stripped from the result
|
|
94
|
+
problemText:string -> reasoning!:string, solutionText:string
|
|
95
|
+
|
|
96
|
+
# Resume parsing: nested objects inside nested arrays
|
|
97
|
+
resumeText:string -> candidateProfile:object{ fullName:string, yearsExperience:number(min 0), skillList:string[], education:object{ schoolName:string, degreeName?:string }[] }
|
|
98
|
+
|
|
99
|
+
# Lead scoring: signature-level description, bounded score, class next step
|
|
100
|
+
"Score sales leads" leadNotes:string -> fitScore:number(min 0, max 100) "0-100 fit", nextStep:class "call, email, drop"
|
|
101
|
+
|
|
102
|
+
# Multimodal: top-level image input with an optional question
|
|
103
|
+
productPhoto:image, question?:string -> productDescription:string, detectedObjects:string[]
|
|
104
|
+
|
|
105
|
+
# Meeting audio: audio input, capped summary, per-item action list
|
|
106
|
+
meetingAudio:audio -> meetingSummary:string(max 1000), actionItems:string(item "one action item")[]
|
|
107
|
+
|
|
108
|
+
# Moderation: class verdict plus structured flagged spans
|
|
109
|
+
postText:string -> moderationVerdict:class "allow, review, block", flaggedSpans:object{ spanText:string, reasonNote:string }[]
|
|
110
|
+
|
|
111
|
+
# Translation: optional locale input
|
|
112
|
+
sourceText:string, targetLocale?:string -> translatedText:string, glossaryHits:string[]
|
|
113
|
+
|
|
114
|
+
# Text-to-SQL: cached schema plus SQL-tagged output
|
|
115
|
+
schemaText:string(cache), questionText:string -> sqlQuery:code(sql), queryNotes?:string(max 200)
|
|
116
|
+
|
|
117
|
+
# Calendar extraction: datetime fields and an optional end
|
|
118
|
+
emailText:string -> eventTitle:string, startsAt:datetime, endsAt?:datetime, attendeeNames:string[]
|
|
119
|
+
|
|
120
|
+
# Booking window: date range, bounded party size, and flexibility flag
|
|
121
|
+
requestText:string -> stayWindow:dateRange, partySize:number(min 1, max 12), flexibleDates:boolean
|
|
122
|
+
|
|
123
|
+
# Contract dates: date fields plus bounded notice period
|
|
124
|
+
contractText:string -> effectiveDate:date, expiryDate?:date, autoRenews:boolean, noticeDays?:number(min 0)
|
|
125
|
+
|
|
126
|
+
# Link audit: URL arrays and an optional primary URL
|
|
127
|
+
pageText:string -> referencedUrls:url[], primaryUrl?:url
|
|
128
|
+
|
|
129
|
+
# Config generation: JSON output plus per-item warnings
|
|
130
|
+
requirementsText:string -> serviceConfig:json, setupWarnings:string(item "one warning")[]
|
|
131
|
+
|
|
132
|
+
# Claims gate: cached policy, bounded confidence, and optional citation
|
|
133
|
+
claimText:string, policyText:string(cache) -> isCovered:boolean, confidenceScore:number(min 0, max 1), citedClause?:string
|
|
134
|
+
|
|
135
|
+
# Earnings extraction: structured period data plus a class outlook
|
|
136
|
+
filingText:string(cache) -> revenueByPeriod:object{ periodLabel:string, amountUsd:number }[], guidanceTone:class "raise, hold, cut"
|
|
137
|
+
|
|
138
|
+
# Pull request review: diff code, cached guide, structured comments, and verdict
|
|
139
|
+
diffText:code(diff), styleGuide?:string(cache) -> reviewComments:object{ filePath:string, lineNumber:number(min 1), commentText:string(max 300) }[], overallVerdict:class "approve, revise"
|
|
140
|
+
|
|
141
|
+
# Incident triage: severity class, optional service, and per-item runbook steps
|
|
142
|
+
alertLog:string -> incidentSeverity:class "sev1, sev2, sev3", suspectedService?:string, runbookSteps:string(item "one step")[]
|
|
143
|
+
|
|
144
|
+
# Product listing: image and file inputs with constrained listing outputs
|
|
145
|
+
productPhoto:image, priceSheet?:file -> listingTitle:string(max 80), bulletPoints:string(item "one selling point")[], priceUsd?:number(min 0)
|
|
146
|
+
|
|
147
|
+
# Study cards: nested object array with an optional difficulty tag
|
|
148
|
+
chapterText:string -> flashCards:object{ questionText:string, answerText:string, difficultyTag?:string }[]
|
|
149
|
+
```
|
|
150
|
+
|
|
44
151
|
## Four Ways to Create Signatures
|
|
45
152
|
|
|
46
153
|
### 1. String-Based (Recommended for simple cases)
|
|
@@ -280,12 +387,20 @@ Bad: `text`, `data`, `input`, `output`, `a`, `x`, `val` (too generic), `1field`
|
|
|
280
387
|
// Data Extraction
|
|
281
388
|
'invoiceText:string -> invoiceNumber:string, totalAmount:number, lineItems:json[]'
|
|
282
389
|
|
|
390
|
+
// Constrained string form (no fluent builder needed)
|
|
391
|
+
'reviewText:string(max 2000) -> rating:number(min 1, max 5), themes:string(item "a theme")[]'
|
|
392
|
+
|
|
393
|
+
// Nested object output in the string form
|
|
394
|
+
'profileText:string -> profile:object{ fullName:string, age?:number(min 0) }'
|
|
395
|
+
|
|
283
396
|
// With description
|
|
284
397
|
'"Answer TypeScript questions" question:string -> answer:string, confidence:number'
|
|
285
398
|
```
|
|
286
399
|
|
|
287
400
|
## Critical Rules
|
|
288
401
|
|
|
402
|
+
- The string form is constraint-complete: reach for modifier bags (`string(max 500)`, `number(min 0, max 10)`, `string(format email)`) and inline `object{ ... }` before switching to fluent/zod just for constraints. Reserve fluent/Standard Schema for zod/valibot-backed fields.
|
|
403
|
+
- The string API is strict — a modifier that does not apply to its type is a parse error (the fluent API silently ignores it).
|
|
289
404
|
- Use `f()` fluent builder, NOT nested `f.array(f.string())` -- those are removed.
|
|
290
405
|
- Field names must be descriptive (not generic like `text`, `data`, `input`).
|
|
291
406
|
- Image/file media types are input-only, top-level only; audio may also be a single top-level output.
|