@electric-ax/agents 0.2.3 → 0.3.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.
Files changed (49) hide show
  1. package/dist/entrypoint.js +474 -737
  2. package/dist/index.cjs +470 -733
  3. package/dist/index.d.cts +68 -35
  4. package/dist/index.d.ts +69 -36
  5. package/dist/index.js +489 -751
  6. package/docs/entities/agents/horton.md +12 -12
  7. package/docs/entities/agents/worker.md +18 -18
  8. package/docs/entities/patterns/blackboard.md +6 -6
  9. package/docs/entities/patterns/dispatcher.md +1 -1
  10. package/docs/entities/patterns/manager-worker.md +1 -1
  11. package/docs/entities/patterns/map-reduce.md +1 -1
  12. package/docs/entities/patterns/pipeline.md +1 -1
  13. package/docs/entities/patterns/reactive-observers.md +2 -2
  14. package/docs/examples/playground.md +42 -26
  15. package/docs/index.md +25 -23
  16. package/docs/quickstart.md +12 -12
  17. package/docs/reference/agent-config.md +20 -12
  18. package/docs/reference/agent-tool.md +1 -1
  19. package/docs/reference/built-in-collections.md +21 -21
  20. package/docs/reference/cli.md +39 -30
  21. package/docs/reference/entity-definition.md +9 -9
  22. package/docs/reference/entity-handle.md +2 -2
  23. package/docs/reference/entity-registry.md +1 -1
  24. package/docs/reference/handler-context.md +34 -18
  25. package/docs/reference/mcp-registry.md +189 -0
  26. package/docs/reference/mcp-server-config.md +226 -0
  27. package/docs/reference/runtime-handler.md +25 -23
  28. package/docs/reference/shared-state-handle.md +7 -7
  29. package/docs/reference/state-collection-proxy.md +1 -1
  30. package/docs/reference/wake-event.md +23 -23
  31. package/docs/usage/app-setup.md +24 -23
  32. package/docs/usage/clients-and-react.md +40 -36
  33. package/docs/usage/configuring-the-agent.md +25 -19
  34. package/docs/usage/context-composition.md +12 -12
  35. package/docs/usage/defining-entities.md +36 -36
  36. package/docs/usage/defining-tools.md +45 -45
  37. package/docs/usage/embedded-builtins.md +54 -43
  38. package/docs/usage/managing-state.md +12 -12
  39. package/docs/usage/mcp-servers.md +354 -0
  40. package/docs/usage/overview.md +50 -45
  41. package/docs/usage/programmatic-runtime-client.md +51 -48
  42. package/docs/usage/shared-state.md +32 -32
  43. package/docs/usage/spawning-and-coordinating.md +9 -9
  44. package/docs/usage/testing.md +14 -14
  45. package/docs/usage/waking-entities.md +13 -13
  46. package/docs/usage/writing-handlers.md +52 -26
  47. package/package.json +9 -4
  48. package/scripts/sync-docs.mjs +42 -0
  49. package/docs/examples/mega-draw.md +0 -106
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Horton agent
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  The built-in Horton assistant - chat, research, code, and dispatch subagents in one entity type.
6
6
  outline: [2, 3]
@@ -8,7 +8,7 @@ outline: [2, 3]
8
8
 
9
9
  # Horton agent
10
10
 
11
- The built-in assistant registered by the Electric Agents dev server. Horton can chat conversationally, search the web, read and edit files, run shell commands, and dispatch subagents (workers) for isolated subtasks.
11
+ The built-in assistant registered by the Electric Agents dev server. Horton can chat conversationally, search the web, read and edit files, run shell commands, and dispatch workers for isolated subtasks.
12
12
 
13
13
  **Source:** [`packages/agents/src/agents/horton.ts`](https://github.com/electric-sql/electric/blob/main/packages/agents/src/agents/horton.ts)
14
14
 
@@ -46,14 +46,14 @@ After the first agent run completes, Horton calls `generateTitle()` (Haiku) to s
46
46
 
47
47
  ## Details
48
48
 
49
- | Property | Value |
50
- | ----------------- | --------------------------------------------------------------------------------- |
51
- | Type name | `horton` |
52
- | Model | `HORTON_MODEL` (`claude-sonnet-4-5-20250929`) |
53
- | Title model | `claude-haiku-4-5-20251001` |
49
+ | Property | Value |
50
+ | ----------------- | ------------------------------------------------- |
51
+ | Type name | `horton` |
52
+ | Model | `HORTON_MODEL` (`claude-sonnet-4-5-20250929`) |
53
+ | Title model | `claude-haiku-4-5-20251001` |
54
54
  | Tools | `ctx.electricTools` + base Horton tool set, plus docs/skill tools when configured |
55
- | Working directory | Passed at bootstrap (defaults to `process.cwd()`) |
56
- | Title generation | Yes, after the first run if no title tag exists |
55
+ | Working directory | Passed at bootstrap (defaults to `process.cwd()`) |
56
+ | Title generation | Yes, after the first run if no title tag exists |
57
57
 
58
58
  ## Extending Horton
59
59
 
@@ -64,10 +64,10 @@ import {
64
64
  HORTON_MODEL,
65
65
  buildHortonSystemPrompt,
66
66
  createHortonTools,
67
- } from '@electric-ax/agents'
67
+ } from "@electric-ax/agents"
68
68
 
69
- registry.define('my-assistant', {
70
- description: 'Horton with an extra custom tool',
69
+ registry.define("my-assistant", {
70
+ description: "Horton with an extra custom tool",
71
71
  async handler(ctx) {
72
72
  const readSet = new Set<string>()
73
73
  ctx.useAgent({
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Worker
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Generic sandboxed subagent type. Spawned by Horton (or any agent) via the spawn_worker tool with a system prompt and a chosen tool subset.
6
6
  outline: [2, 3]
@@ -19,7 +19,7 @@ interface WorkerArgs {
19
19
  systemPrompt: string
20
20
  tools?: Array<WorkerToolName>
21
21
  sharedDb?: { id: string; schema: SharedStateSchemaMap }
22
- sharedDbToolMode?: 'full' | 'write-only'
22
+ sharedDbToolMode?: "full" | "write-only"
23
23
  }
24
24
  ```
25
25
 
@@ -36,13 +36,13 @@ interface WorkerArgs {
36
36
 
37
37
  ```ts
38
38
  type WorkerToolName =
39
- | 'bash'
40
- | 'read'
41
- | 'write'
42
- | 'edit'
43
- | 'brave_search'
44
- | 'fetch_url'
45
- | 'spawn_worker'
39
+ | "bash"
40
+ | "read"
41
+ | "write"
42
+ | "edit"
43
+ | "brave_search"
44
+ | "fetch_url"
45
+ | "spawn_worker"
46
46
  ```
47
47
 
48
48
  These are the same primitives Horton uses. Pick the smallest subset the worker needs — tools are the worker's permission set.
@@ -56,9 +56,9 @@ The canonical way to spawn a worker is the `spawn_worker` tool, which Horton cal
56
56
  ```ts
57
57
  spawn_worker({
58
58
  systemPrompt:
59
- 'You are a focused researcher. Find the three most-cited papers on X and return their titles, authors, and DOIs as a markdown table.',
60
- tools: ['brave_search', 'fetch_url'],
61
- initialMessage: 'Begin research now.',
59
+ "You are a focused researcher. Find the three most-cited papers on X and return their titles, authors, and DOIs as a markdown table.",
60
+ tools: ["brave_search", "fetch_url"],
61
+ initialMessage: "Begin research now.",
62
62
  })
63
63
  ```
64
64
 
@@ -93,10 +93,10 @@ When you finish, respond with a concise report covering what was done and any ke
93
93
 
94
94
  ## Details
95
95
 
96
- | Property | Value |
97
- | ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
98
- | Type name | `worker` |
99
- | Model | `HORTON_MODEL` (`claude-sonnet-4-5-20250929`) |
100
- | Tools | Subset of 7 primitives plus optional shared-state tools. **No `ctx.electricTools`.** |
101
- | Working directory | Provided to `registerWorker` at bootstrap |
96
+ | Property | Value |
97
+ | ----------------- | --------------------------------------------------------------------- |
98
+ | Type name | `worker` |
99
+ | Model | `HORTON_MODEL` (`claude-sonnet-4-5-20250929`) |
100
+ | Tools | Subset of 7 primitives plus optional shared-state tools. **No `ctx.electricTools`.** |
101
+ | Working directory | Provided to `registerWorker` at bootstrap |
102
102
  | Description | `Internal — generic worker spawned by other agents. Configure via spawn args (systemPrompt + tools + optional sharedDb).` |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Blackboard (shared state)
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Multi-agent coordination using shared state as a common data structure for reads and writes.
6
6
  outline: [2, 3]
@@ -23,12 +23,12 @@ const debateSchema = {
23
23
  arguments: {
24
24
  schema: z.object({
25
25
  key: z.string(),
26
- side: z.enum(['pro', 'con']),
26
+ side: z.enum(["pro", "con"]),
27
27
  text: z.string(),
28
28
  round: z.number(),
29
29
  }),
30
- type: 'shared:argument',
31
- primaryKey: 'key',
30
+ type: "shared:argument",
31
+ primaryKey: "key",
32
32
  },
33
33
  }
34
34
  ```
@@ -36,7 +36,7 @@ const debateSchema = {
36
36
  ### Registration
37
37
 
38
38
  ```ts
39
- import { db } from '@electric-ax/agents-runtime'
39
+ import { db } from "@electric-ax/agents-runtime"
40
40
 
41
41
  export function registerDebate(registry: EntityRegistry) {
42
42
  registry.define(`debate`, {
@@ -97,7 +97,7 @@ const args = shared.arguments.toArray
97
97
  ### State transitions
98
98
 
99
99
  ```ts
100
- type DebateStatus = 'idle' | 'debating' | 'ruling' | 'done'
100
+ type DebateStatus = "idle" | "debating" | "ruling" | "done"
101
101
  ```
102
102
 
103
103
  ## Other blackboard variants
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Dispatcher
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Message routing pattern that classifies incoming messages and dispatches to specialist agents.
6
6
  outline: [2, 3]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Manager-Worker
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Coordination pattern where a parent spawns specialist children, waits for completion, and synthesizes results.
6
6
  outline: [2, 3]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Map-Reduce
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Parallel processing pattern that splits work into chunks, processes simultaneously, and reduces results.
6
6
  outline: [2, 3]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Pipeline
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Sequential processing pattern where each stage's output feeds into the next via state transitions.
6
6
  outline: [2, 3]
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Reactive observers
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Pattern for entities that watch others and react to changes using ctx.observe() with wake conditions.
6
6
  outline: [2, 3]
@@ -66,7 +66,7 @@ The monitor wraps the base observe tool to also transition its own state to `obs
66
66
  The `observe_entity` tool lets the LLM decide what to watch:
67
67
 
68
68
  ```ts
69
- import { entity } from '@electric-ax/agents-runtime'
69
+ import { entity } from "@electric-ax/agents-runtime"
70
70
 
71
71
  export function createObserveTool(ctx: HandlerContext): AgentTool {
72
72
  return {
@@ -1,46 +1,62 @@
1
1
  ---
2
- title: Pattern references
3
- titleTemplate: '... - Electric Agents'
2
+ title: Playground
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
- Electric Agents pattern references for standalone, coordination, blackboard, and reactive designs.
5
+ Technical examples for experimenting with Electric Agents coordination patterns.
6
6
  outline: [2, 3]
7
7
  ---
8
8
 
9
- # Pattern references
9
+ # Playground
10
10
 
11
- Electric Agents pattern references live in the monorepo under `packages/agents-runtime/skills/designing-entities/references/patterns/`.
11
+ The [Electric Agents Playground](https://github.com/electric-sql/electric/tree/main/examples/agents-playground) is a collection of technical examples for trying coordination patterns against a local Electric Agents server.
12
12
 
13
13
  ## What it includes
14
14
 
15
- The patterns are organized into four categories.
15
+ The playground currently includes two entity patterns.
16
16
 
17
- ### Standalone
17
+ ### Perspectives
18
18
 
19
- - `single-agent` --- one entity handles the full task itself
19
+ Perspectives is a manager-worker example. A manager agent spawns an optimist and a critic to examine the same question from different viewpoints, then synthesizes their responses into a balanced analysis.
20
20
 
21
- ### Coordination
21
+ It demonstrates:
22
22
 
23
- - `manager-worker` --- multi-perspective analysis (optimist/pessimist/pragmatist)
24
- - `dispatcher` --- routes tasks to the appropriate agent type
25
- - `pipeline` --- sequential worker stages
26
- - `map-reduce` --- parallel chunk processing
23
+ - Spawning child agents from a custom tool.
24
+ - Waking the manager when child runs finish.
25
+ - Tracking child entity URLs in state.
26
+ - Synthesizing worker outputs into a final response.
27
27
 
28
- ### Blackboard (shared state)
28
+ ### Researcher
29
29
 
30
- - `blackboard` --- multiple workers coordinate through shared state
30
+ Researcher is a coordinator example. It decomposes complex research questions into specialist sub-questions, spawns workers for each slice, and synthesizes the findings into a comprehensive answer with citations.
31
31
 
32
- ### Reactive
32
+ It demonstrates:
33
33
 
34
- - `reactive-observers` --- observes entity streams and reacts to changes
34
+ - Dynamic fan-out based on the shape of the user's question.
35
+ - Specialist worker agents focused on distinct research tasks.
36
+ - Wake-on-finish coordination between coordinator and workers.
37
+ - Final synthesis from multiple child reports.
35
38
 
36
- ## Source references
39
+ ## Run it
37
40
 
38
- - [`single-agent`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/single-agent.md)
39
- - [`manager-worker`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/manager-worker.md)
40
- - [`dispatcher`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/dispatcher.md)
41
- - [`pipeline`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/pipeline.md)
42
- - [`map-reduce`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/map-reduce.md)
43
- - [`blackboard`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/blackboard.md)
44
- - [`reactive-observers`](https://github.com/electric-sql/electric/blob/main/packages/agents-runtime/skills/designing-entities/references/patterns/reactive-observers.md)
41
+ Start the local agents infrastructure from the monorepo root:
45
42
 
46
- See [Agents & Patterns](../usage/spawning-and-coordinating.md) for detailed documentation of each pattern.
43
+ ```bash
44
+ npx electric-ax agents start
45
+ ```
46
+
47
+ Then configure and run the playground:
48
+
49
+ ```bash
50
+ cd examples/agents-playground
51
+ cp .env.example .env
52
+ pnpm install
53
+ pnpm dev
54
+ ```
55
+
56
+ The app server starts on port `3000` and registers entity types with the agent server on port `4437`.
57
+
58
+ ## Source
59
+
60
+ The source code is in [`examples/agents-playground`](https://github.com/electric-sql/electric/tree/main/examples/agents-playground).
61
+
62
+ See [spawning & coordinating](../usage/spawning-and-coordinating.md) for the underlying coordination concepts.
package/docs/index.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Electric Agents
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  The durable runtime for long-lived agents — entities, handlers, wakes, agent loops, and coordination, built on Electric Streams, TanStack DB, and pi.
6
6
  outline: [2, 3]
@@ -22,7 +22,7 @@ Every step — runs, tool calls, text deltas, state changes — is appended to t
22
22
 
23
23
  <EntityOverviewDiagram />
24
24
 
25
- Start with the [Quickstart](/docs/agents/quickstart) to run the built-in `horton` agent and connect your own app in a few minutes. The [Usage overview](/docs/agents/usage/overview) summarises the full developer surface in a single page.
25
+ Start with the [Quickstart](/docs/agents/quickstart) to run the built-in `horton` and `worker` entities and connect your own app in a few minutes. The [Usage overview](/docs/agents/usage/overview) summarises the full developer surface in a single page.
26
26
 
27
27
  ## How it works
28
28
 
@@ -45,8 +45,8 @@ Use entities to model anything long-lived and addressable — an agent session,
45
45
  ```ts
46
46
  const registry = createEntityRegistry()
47
47
 
48
- registry.define('assistant', {
49
- description: 'A general-purpose AI assistant',
48
+ registry.define("assistant", {
49
+ description: "A general-purpose AI assistant",
50
50
  async handler(ctx) {
51
51
  // ...
52
52
  },
@@ -58,12 +58,12 @@ registry.define('assistant', {
58
58
  The function that runs when an entity wakes. Receives a [`HandlerContext`](/docs/agents/reference/handler-context) (`ctx`) and a [`WakeEvent`](/docs/agents/reference/wake-event) (`wake`). The handler decides how to respond: configure an agent, update state, spawn children, or any combination. See [Writing handlers](/docs/agents/usage/writing-handlers).
59
59
 
60
60
  ```ts
61
- registry.define('support', {
61
+ registry.define("support", {
62
62
  async handler(ctx, wake) {
63
- if (wake.type === 'message_received') {
63
+ if (wake.type === "message_received") {
64
64
  ctx.useAgent({
65
- systemPrompt: 'You are a support agent.',
66
- model: 'claude-sonnet-4-5-20250929',
65
+ systemPrompt: "You are a support agent.",
66
+ model: "claude-sonnet-4-5-20250929",
67
67
  tools: [...ctx.electricTools, searchKbTool],
68
68
  })
69
69
  await ctx.agent.run()
@@ -94,7 +94,7 @@ async handler(ctx, wake) {
94
94
  Custom persistent collections on the entity. Defined as part of the [entity definition](/docs/agents/reference/entity-definition) and accessed through `ctx.db` alongside the [built-in collections](#built-in-collections). State is local to the entity, typed, and survives restarts. Use it for things that belong to the entity but aren't part of the agent's event stream — an order's items, a research job's findings, a chat session's TODOs. See [Managing state](/docs/agents/usage/managing-state).
95
95
 
96
96
  ```ts
97
- registry.define('tracker', {
97
+ registry.define("tracker", {
98
98
  state: {
99
99
  items: {
100
100
  schema: z.object({
@@ -102,16 +102,16 @@ registry.define('tracker', {
102
102
  name: z.string(),
103
103
  done: z.boolean(),
104
104
  }),
105
- primaryKey: 'key',
105
+ primaryKey: "key",
106
106
  },
107
107
  },
108
108
  async handler(ctx) {
109
109
  // read
110
- const item = ctx.db.collections.items.get('item-1')
110
+ const item = ctx.db.collections.items.get("item-1")
111
111
 
112
112
  // write
113
113
  ctx.db.actions.items_insert({
114
- row: { key: 'item-2', name: 'New', done: false },
114
+ row: { key: "item-2", name: "New", done: false },
115
115
  })
116
116
  },
117
117
  })
@@ -123,8 +123,8 @@ The core pattern is [`ctx.useAgent()`](/docs/agents/reference/agent-config) foll
123
123
 
124
124
  ```ts
125
125
  ctx.useAgent({
126
- systemPrompt: 'You are a helpful assistant.',
127
- model: 'claude-sonnet-4-5-20250929',
126
+ systemPrompt: "You are a helpful assistant.",
127
+ model: "claude-sonnet-4-5-20250929",
128
128
  tools: [...ctx.electricTools, myCustomTool],
129
129
  })
130
130
 
@@ -135,19 +135,21 @@ await ctx.agent.run()
135
135
 
136
136
  Functions the LLM can call during the agent loop. Each tool has a name, description, parameters (defined with [TypeBox](https://github.com/sinclairzx81/typebox) or any [Standard Schema](https://standardschema.dev) validator), and an execute function. Tools run in the handler's context and have access to the entity's state and coordination primitives. See [Defining tools](/docs/agents/usage/defining-tools) and the [`AgentTool` reference](/docs/agents/reference/agent-tool).
137
137
 
138
+ External tools, resources, and prompts can also be loaded from [Model Context Protocol](https://modelcontextprotocol.io) servers — declared in `mcp.json`, the desktop app's `settings.json`, or programmatically. See [MCP servers](/docs/agents/usage/mcp-servers).
139
+
138
140
  ```ts
139
141
  const searchKbTool: AgentTool = {
140
- name: 'search_kb',
141
- label: 'Search knowledge base',
142
- description: 'Search the knowledge base',
142
+ name: "search_kb",
143
+ label: "Search knowledge base",
144
+ description: "Search the knowledge base",
143
145
  parameters: Type.Object({
144
- query: Type.String({ description: 'Search query' }),
146
+ query: Type.String({ description: "Search query" }),
145
147
  }),
146
148
  execute: async (_toolCallId, params) => {
147
149
  const { query } = params as { query: string }
148
150
  const results = await searchKnowledgeBase(query)
149
151
  return {
150
- content: [{ type: 'text', text: JSON.stringify(results) }],
152
+ content: [{ type: "text", text: JSON.stringify(results) }],
151
153
  details: {},
152
154
  }
153
155
  },
@@ -191,18 +193,18 @@ const allRuns = ctx.db.collections.runs.toArray
191
193
  const lastError = ctx.db.collections.errors.toArray.at(-1)
192
194
 
193
195
  // from outside — load an entity's stream into a local DB
194
- const client = createAgentsClient({ baseUrl: 'http://localhost:4437' })
195
- const db = await client.observe(entity('/support/ticket-42'))
196
+ const client = createAgentsClient({ baseUrl: "http://localhost:4437" })
197
+ const db = await client.observe(entity("/support/ticket-42"))
196
198
  console.log(db.collections.texts.toArray)
197
199
  ```
198
200
 
199
201
  ## Next steps
200
202
 
201
- - [Quickstart](/docs/agents/quickstart) — run the built-in `horton` agent and connect your own app.
203
+ - [Quickstart](/docs/agents/quickstart) — run the built-in `horton` and `worker` entities and connect your own app.
202
204
  - [Usage overview](/docs/agents/usage/overview) — the full developer surface on one page.
203
205
  - [Defining entities](/docs/agents/usage/defining-entities) — entity types, schemas, and configuration.
204
206
  - [Writing handlers](/docs/agents/usage/writing-handlers) — handler lifecycle and the `ctx` API.
205
207
  - [Configuring the agent](/docs/agents/usage/configuring-the-agent) — `useAgent`, models, tools, and streaming.
206
208
  - [Spawning & coordinating](/docs/agents/usage/spawning-and-coordinating) — multi-entity topologies and shared state.
207
- - [Built-in agents](/docs/agents/entities/agents/horton) — Horton and Worker, the agents that ship with the runtime.
209
+ - [Built-in agents](/docs/agents/entities/agents/horton) — Horton, Worker, and Coder, the agents that ship with the runtime.
208
210
  - [Examples](/docs/agents/examples/playground) — pattern walkthroughs and demo apps.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Quickstart
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Run the Electric Agents runtime and the built-in Horton assistant with a single CLI command, then connect from the web UI or define your own entities.
6
6
  outline: [2, 3]
@@ -19,7 +19,7 @@ npx electric-ax agents quickstart
19
19
  - **Node.js 18+**.
20
20
  - **[Docker](https://docs.docker.com/get-docker/)**. The runtime server, Postgres, and Electric run as containers.
21
21
  - **An [Anthropic API key](https://console.anthropic.com/settings/keys)**. Used by the built-in Horton agent.
22
- - _(Optional)_ A **[Brave Search API key](https://brave.com/search/api/)** if you want Horton to be able to search the web.
22
+ - *(Optional)* A **[Brave Search API key](https://brave.com/search/api/)** if you want Horton to be able to search the web.
23
23
 
24
24
  ## Set your API key
25
25
 
@@ -94,25 +94,25 @@ npm install --save-dev tsx
94
94
  Create `server.ts`:
95
95
 
96
96
  ```ts
97
- import http from 'node:http'
97
+ import http from "node:http"
98
98
  import {
99
99
  createEntityRegistry,
100
100
  createRuntimeHandler,
101
- } from '@electric-ax/agents-runtime'
101
+ } from "@electric-ax/agents-runtime"
102
102
 
103
103
  const ELECTRIC_AGENTS_URL =
104
- process.env.ELECTRIC_AGENTS_URL ?? 'http://localhost:4437'
104
+ process.env.ELECTRIC_AGENTS_URL ?? "http://localhost:4437"
105
105
  const PORT = Number(process.env.PORT ?? 3000)
106
106
  const SERVE_URL = process.env.SERVE_URL ?? `http://localhost:${PORT}`
107
107
 
108
108
  const registry = createEntityRegistry()
109
109
 
110
- registry.define('assistant', {
111
- description: 'A general-purpose AI assistant',
110
+ registry.define("assistant", {
111
+ description: "A general-purpose AI assistant",
112
112
  async handler(ctx) {
113
113
  ctx.useAgent({
114
- systemPrompt: 'You are a helpful assistant.',
115
- model: 'claude-sonnet-4-5-20250929',
114
+ systemPrompt: "You are a helpful assistant.",
115
+ model: "claude-sonnet-4-5-20250929",
116
116
  tools: [...ctx.electricTools],
117
117
  })
118
118
  await ctx.agent.run()
@@ -126,7 +126,7 @@ const runtime = createRuntimeHandler({
126
126
  })
127
127
 
128
128
  const server = http.createServer(async (req, res) => {
129
- if (req.url === '/webhook' && req.method === 'POST') {
129
+ if (req.url === "/webhook" && req.method === "POST") {
130
130
  await runtime.onEnter(req, res)
131
131
  return
132
132
  }
@@ -186,7 +186,7 @@ npx electric-ax agents stop --remove-volumes # stop containers and wipe data
186
186
 
187
187
  ```sh
188
188
  npx electric-ax agents start # runtime server + UI (background, Docker)
189
- npx electric-ax agents start-builtin # built-in Horton + worker (foreground)
189
+ npx electric-ax agents start-builtin # built-in Horton and worker (foreground)
190
190
  ```
191
191
 
192
192
  See the [CLI reference](./reference/cli#start) for the full set of commands.
@@ -198,4 +198,4 @@ See the [CLI reference](./reference/cli#start) for the full set of commands.
198
198
  - [Defining entities](./usage/defining-entities) — entity types, schemas, and configuration.
199
199
  - [Writing handlers](./usage/writing-handlers) — handler lifecycle and the `ctx` API.
200
200
  - [Configuring the agent](./usage/configuring-the-agent) — `useAgent`, models, tools, and streaming.
201
- - [Built-in agents](./entities/agents/horton) — Horton and Worker, the agents that ship with the runtime.
201
+ - [Built-in agents](./entities/agents/horton) — Horton, Worker, and Coder, the agents that ship with the runtime.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: AgentConfig
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  API reference for AgentConfig: system prompt, model, tools, streaming, and test responses.
6
6
  outline: [2, 3]
@@ -19,20 +19,26 @@ interface AgentConfig {
19
19
  provider?: KnownProvider
20
20
  tools: AgentTool[]
21
21
  streamFn?: StreamFn
22
+ getApiKey?: (
23
+ provider: string
24
+ ) => Promise<string | undefined> | string | undefined
25
+ onPayload?: SimpleStreamOptions["onPayload"]
22
26
  testResponses?: string[] | TestResponseFn
23
27
  }
24
28
  ```
25
29
 
26
30
  ## Fields
27
31
 
28
- | Field | Type | Required | Description |
29
- | --------------- | ---------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
30
- | `systemPrompt` | `string` | Yes | System prompt sent to the LLM on each step. |
31
- | `model` | `string \| Model<any>` | Yes | Model identifier (e.g. `"claude-sonnet-4-5-20250929"`) or a resolved model object. |
32
- | `provider` | `KnownProvider` | No | Provider to use when `model` is a string. Defaults to `"anthropic"`. |
32
+ | Field | Type | Required | Description |
33
+ | --------------- | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------- |
34
+ | `systemPrompt` | `string` | Yes | System prompt sent to the LLM on each step. |
35
+ | `model` | `string \| Model<any>` | Yes | Model identifier (e.g. `"claude-sonnet-4-5-20250929"`) or a resolved model object. |
36
+ | `provider` | `KnownProvider` | No | Provider to use when `model` is a string. Defaults to `"anthropic"`. |
33
37
  | `tools` | `AgentTool[]` | Yes | Tools available to the LLM. Spread `ctx.electricTools` when your runtime host provides runtime-level tools. See [`AgentTool`](./agent-tool). |
34
- | `streamFn` | `StreamFn` | No | Optional streaming callback passed to the underlying agent. |
35
- | `testResponses` | `string[] \| TestResponseFn` | No | Mock LLM responses for testing. When set, no real LLM calls are made. |
38
+ | `streamFn` | `StreamFn` | No | Optional streaming callback passed to the underlying agent. |
39
+ | `getApiKey` | `(provider) => string \| Promise<string> \| undefined` | No | Optional API-key resolver passed through to the model layer. |
40
+ | `onPayload` | `SimpleStreamOptions["onPayload"]` | No | Optional callback for raw streaming payloads from the model layer. |
41
+ | `testResponses` | `string[] \| TestResponseFn` | No | Mock LLM responses for testing. When set, no real LLM calls are made. |
36
42
 
37
43
  ## TestResponseFn
38
44
 
@@ -69,14 +75,16 @@ interface AgentHandle {
69
75
 
70
76
  ```ts
71
77
  interface AgentRunResult {
78
+ result?: unknown
72
79
  writes: ChangeEvent[]
73
80
  toolCalls: Array<{ name: string; args: unknown; result: unknown }>
74
81
  usage: { tokens: number; duration: number }
75
82
  }
76
83
  ```
77
84
 
78
- | Field | Type | Description |
79
- | ----------- | -------------------------------------- | --------------------------------------------------------------------------------------- |
80
- | `writes` | `ChangeEvent[]` | Currently returned as an empty array placeholder. |
81
- | `toolCalls` | `Array<{ name, args, result }>` | Currently returned as an empty array placeholder. |
85
+ | Field | Type | Description |
86
+ | ----------- | -------------------------------------- | --------------------------------------------------------------------------- |
87
+ | `result` | `unknown` | Optional final result from the underlying agent adapter. |
88
+ | `writes` | `ChangeEvent[]` | Currently returned as an empty array placeholder. |
89
+ | `toolCalls` | `Array<{ name, args, result }>` | Currently returned as an empty array placeholder. |
82
90
  | `usage` | `{ tokens: number; duration: number }` | Currently returned as `{ tokens: 0, duration: 0 }` until usage aggregation is wired in. |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: AgentTool
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Interface reference for AgentTool: name, description, TypeBox parameters schema, and execute function.
6
6
  outline: [2, 3]