@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: Clients & React
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Observe Electric Agents entities from app code, build reactive StreamDB handles,
6
6
  and render chat timelines with the React useChat hook.
@@ -17,20 +17,24 @@ Use the client APIs when you need to observe agents from application code rather
17
17
 
18
18
  ```ts
19
19
  import {
20
+ codingSession,
20
21
  createAgentsClient,
21
22
  entity,
22
23
  entities,
23
- } from '@electric-ax/agents-runtime'
24
+ } from "@electric-ax/agents-runtime"
24
25
 
25
- const client = createAgentsClient({ baseUrl: 'http://localhost:4437' })
26
+ const client = createAgentsClient({ baseUrl: "http://localhost:4437" })
26
27
 
27
28
  // Observe a single entity stream.
28
- const entityDb = await client.observe(entity('/horton/onboarding'))
29
+ const entityDb = await client.observe(entity("/horton/onboarding"))
29
30
  console.log(entityDb.collections.texts.toArray)
30
31
 
31
32
  // Observe the entity membership stream for a tag query.
32
- const membersDb = await client.observe(entities({ tags: { project: 'alpha' } }))
33
+ const membersDb = await client.observe(
34
+ entities({ tags: { project: "alpha" } })
35
+ )
33
36
  console.log(membersDb.collections.members.toArray)
37
+
34
38
  ```
35
39
 
36
40
  ### Types
@@ -58,17 +62,17 @@ interface AgentsClient {
58
62
 
59
63
  The same source helpers used by `ctx.observe()` can be used with `AgentsClient`.
60
64
 
61
- | Helper | Use case |
62
- | -------------------- | --------------------------------------------------- |
63
- | `entity(url)` | Observe one entity by URL. |
65
+ | Helper | Use case |
66
+ | ------------------- | ---------------------------------------------------- |
67
+ | `entity(url)` | Observe one entity by URL. |
64
68
  | `entities({ tags })` | Observe the entity membership stream matching tags. |
65
- | `db(id, schema)` | Observe a shared-state stream. |
66
- | `cron(expression)` | Build a cron source for wake subscriptions. |
69
+ | `db(id, schema)` | Observe a shared-state stream. |
70
+ | `cron(expression)` | Build a cron source for wake subscriptions. |
67
71
 
68
72
  ```ts
69
- import { db } from '@electric-ax/agents-runtime'
73
+ import { db } from "@electric-ax/agents-runtime"
70
74
 
71
- const shared = await client.observe(db('research-123', researchSchema))
75
+ const shared = await client.observe(db("research-123", researchSchema))
72
76
  ```
73
77
 
74
78
  ## React useChat
@@ -76,12 +80,12 @@ const shared = await client.observe(db('research-123', researchSchema))
76
80
  `@electric-ax/agents-runtime/react` exports `useChat()`, a React hook that turns an `EntityStreamDB` into sections suitable for a chat UI.
77
81
 
78
82
  ```tsx
79
- import { useEffect, useState } from 'react'
80
- import { createAgentsClient, entity } from '@electric-ax/agents-runtime'
81
- import { useChat } from '@electric-ax/agents-runtime/react'
82
- import type { EntityStreamDB } from '@electric-ax/agents-runtime'
83
+ import { useEffect, useState } from "react"
84
+ import { createAgentsClient, entity } from "@electric-ax/agents-runtime"
85
+ import { useChat } from "@electric-ax/agents-runtime/react"
86
+ import type { EntityStreamDB } from "@electric-ax/agents-runtime"
83
87
 
84
- const client = createAgentsClient({ baseUrl: 'http://localhost:4437' })
88
+ const client = createAgentsClient({ baseUrl: "http://localhost:4437" })
85
89
 
86
90
  export function AgentConversation({ entityUrl }: { entityUrl: string }) {
87
91
  const [db, setDb] = useState<EntityStreamDB | null>(null)
@@ -109,10 +113,10 @@ export function AgentConversation({ entityUrl }: { entityUrl: string }) {
109
113
  <ol>
110
114
  {chat.sections.map((section, index) => (
111
115
  <li key={index}>
112
- {section.kind === 'user_message'
116
+ {section.kind === "user_message"
113
117
  ? section.text
114
118
  : section.items.map((item) =>
115
- item.kind === 'text' ? item.text : item.toolName
119
+ item.kind === "text" ? item.text : item.toolName
116
120
  )}
117
121
  </li>
118
122
  ))}
@@ -126,7 +130,7 @@ export function AgentConversation({ entityUrl }: { entityUrl: string }) {
126
130
  ```ts
127
131
  interface UseChatResult {
128
132
  sections: EntityTimelineSection[]
129
- state: 'pending' | 'queued' | 'working' | 'idle' | 'error'
133
+ state: "pending" | "queued" | "working" | "idle" | "error"
130
134
  runs: IncludesRun[]
131
135
  inbox: IncludesInboxMessage[]
132
136
  wakes: IncludesWakeMessage[]
@@ -151,34 +155,34 @@ import {
151
155
  normalizeEntityTimelineData,
152
156
  timelineMessages,
153
157
  timelineToMessages,
154
- } from '@electric-ax/agents-runtime'
158
+ } from "@electric-ax/agents-runtime"
155
159
  ```
156
160
 
157
161
  Use these when you already have an `EntityStreamDB` and want to build your own UI integration.
158
162
 
159
- | Helper | Purpose |
160
- | ----------------------------------- | ---------------------------------------------------------------------- |
161
- | `createEntityIncludesQuery(db)` | Builds the TanStack DB query used by `useChat`. |
162
- | `normalizeEntityTimelineData()` | Normalizes and sorts nested run, text, tool, wake, and entity data. |
163
- | `getEntityState(runs, inbox)` | Computes `pending`, `queued`, `working`, `idle`, or `error`. |
164
- | `buildSections(runs, inbox)` | Builds chat-friendly user/agent sections. |
165
- | `buildTimelineEntries(runs, inbox)` | Builds keyed timeline entries with response timestamps. |
166
- | `materializeTimeline(data)` | Converts normalized timeline data into prompt-oriented timeline items. |
167
- | `defaultProjection(item)` | Projects one timeline item into LLM messages. |
168
- | `timelineMessages(db, opts?)` | Reads an entity DB and returns timestamped LLM messages. |
169
- | `timelineToMessages(db)` | Convenience wrapper returning plain LLM messages. |
163
+ | Helper | Purpose |
164
+ | ------------------------------ | ------------------------------------------------------------- |
165
+ | `createEntityIncludesQuery(db)` | Builds the TanStack DB query used by `useChat`. |
166
+ | `normalizeEntityTimelineData()` | Normalizes and sorts nested run, text, tool, wake, and entity data. |
167
+ | `getEntityState(runs, inbox)` | Computes `pending`, `queued`, `working`, `idle`, or `error`. |
168
+ | `buildSections(runs, inbox)` | Builds chat-friendly user/agent sections. |
169
+ | `buildTimelineEntries(runs, inbox)` | Builds keyed timeline entries with response timestamps. |
170
+ | `materializeTimeline(data)` | Converts normalized timeline data into prompt-oriented timeline items. |
171
+ | `defaultProjection(item)` | Projects one timeline item into LLM messages. |
172
+ | `timelineMessages(db, opts?)` | Reads an entity DB and returns timestamped LLM messages. |
173
+ | `timelineToMessages(db)` | Convenience wrapper returning plain LLM messages. |
170
174
 
171
175
  ## CLI Entity Stream DB
172
176
 
173
177
  The `electric-ax/entity-stream-db` subpath exposes a convenience loader used by CLI and UI code:
174
178
 
175
179
  ```ts
176
- import { createEntityStreamDB } from 'electric-ax/entity-stream-db'
180
+ import { createEntityStreamDB } from "electric-ax/entity-stream-db"
177
181
 
178
182
  const { db, close } = await createEntityStreamDB({
179
- baseUrl: 'http://localhost:4437',
180
- entityUrl: '/horton/onboarding',
181
- initialOffset: '0',
183
+ baseUrl: "http://localhost:4437",
184
+ entityUrl: "/horton/onboarding",
185
+ initialOffset: "0",
182
186
  })
183
187
 
184
188
  try {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Configuring the agent
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Set up LLM agents with ctx.useAgent(), including model selection, system prompts, tools, and test responses.
6
6
  outline: [2, 3]
@@ -19,18 +19,22 @@ interface AgentConfig {
19
19
  provider?: KnownProvider
20
20
  tools: AgentTool[]
21
21
  streamFn?: StreamFn
22
+ getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined
23
+ onPayload?: SimpleStreamOptions["onPayload"]
22
24
  testResponses?: string[] | TestResponseFn
23
25
  }
24
26
  ```
25
27
 
26
- | Field | Required | Description |
27
- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
28
- | `systemPrompt` | Yes | The system prompt passed to the LLM. |
29
- | `model` | Yes | Model identifier string or resolved model object. |
30
- | `provider` | No | Provider to use when `model` is a string. Defaults to `"anthropic"`. |
28
+ | Field | Required | Description |
29
+ | --------------- | -------- | ----------------------------------------------------------------------- |
30
+ | `systemPrompt` | Yes | The system prompt passed to the LLM. |
31
+ | `model` | Yes | Model identifier string or resolved model object. |
32
+ | `provider` | No | Provider to use when `model` is a string. Defaults to `"anthropic"`. |
31
33
  | `tools` | Yes | Array of tools available to the agent. Spread `ctx.electricTools` when your runtime host provides runtime-level tools. |
32
- | `streamFn` | No | Optional streaming callback passed to the underlying agent. |
33
- | `testResponses` | No | Mock responses for testing without calling the LLM. |
34
+ | `streamFn` | No | Optional streaming callback passed to the underlying agent. |
35
+ | `getApiKey` | No | Optional API-key resolver passed through to the model layer. |
36
+ | `onPayload` | No | Optional callback for raw streaming payloads from the model layer. |
37
+ | `testResponses` | No | Mock responses for testing without calling the LLM. |
34
38
 
35
39
  ## Basic usage
36
40
 
@@ -71,16 +75,18 @@ Returns an `AgentRunResult`:
71
75
 
72
76
  ```ts
73
77
  type AgentRunResult = {
78
+ result?: unknown
74
79
  writes: ChangeEvent[]
75
80
  toolCalls: Array<{ name: string; args: unknown; result: unknown }>
76
81
  usage: { tokens: number; duration: number }
77
82
  }
78
83
  ```
79
84
 
80
- | Field | Description |
81
- | ----------- | --------------------------------------------------------------------------------------- |
82
- | `writes` | Currently returned as an empty array placeholder. |
83
- | `toolCalls` | Currently returned as an empty array placeholder. |
85
+ | Field | Description |
86
+ | ----------- | --------------------------------------------------------------------------- |
87
+ | `result` | Optional final result from the underlying agent adapter. |
88
+ | `writes` | Currently returned as an empty array placeholder. |
89
+ | `toolCalls` | Currently returned as an empty array placeholder. |
84
90
  | `usage` | Currently returned as `{ tokens: 0, duration: 0 }` until usage aggregation is wired in. |
85
91
 
86
92
  ## AgentHandle
@@ -100,8 +106,8 @@ You must call `useAgent` before calling `run()`. Calling `ctx.agent.run()` witho
100
106
  When `model` is a string, the runtime resolves it through the configured `provider` (default `"anthropic"`). You can also pass a resolved `Model` object directly.
101
107
 
102
108
  ```ts
103
- model: 'claude-sonnet-4-5-20250929'
104
- provider: 'anthropic'
109
+ model: "claude-sonnet-4-5-20250929"
110
+ provider: "anthropic"
105
111
  ```
106
112
 
107
113
  ## Test responses
@@ -112,10 +118,10 @@ For testing handlers without making LLM calls, pass `testResponses`. Two forms a
112
118
 
113
119
  ```ts
114
120
  ctx.useAgent({
115
- systemPrompt: '...',
116
- model: 'claude-sonnet-4-5-20250929',
121
+ systemPrompt: "...",
122
+ model: "claude-sonnet-4-5-20250929",
117
123
  tools: [...ctx.electricTools],
118
- testResponses: ['Hello! How can I help?', 'Sure, I can do that.'],
124
+ testResponses: ["Hello! How can I help?", "Sure, I can do that."],
119
125
  })
120
126
  ```
121
127
 
@@ -125,8 +131,8 @@ ctx.useAgent({
125
131
  ctx.useAgent({
126
132
  // ...
127
133
  testResponses: async (message, bridge) => {
128
- if (message.includes('calculate')) {
129
- return 'The answer is 42.'
134
+ if (message.includes("calculate")) {
135
+ return "The answer is 42."
130
136
  }
131
137
  return undefined // emits no automatic text response
132
138
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Context composition
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Control what goes into the agent's context window using ctx.useContext() with token-budgeted sources, cache tiers, and imperative context entries.
6
6
  outline: [2, 3]
@@ -25,14 +25,14 @@ ctx.useContext({
25
25
  sourceBudget: 18_000,
26
26
  sources: {
27
27
  docs: {
28
- content: () => '# Reference docs\n...',
28
+ content: () => "# Reference docs\n...",
29
29
  max: 6_000,
30
- cache: 'stable',
30
+ cache: "stable",
31
31
  },
32
32
  conversation: {
33
33
  content: () => ctx.timelineMessages(),
34
34
  max: 12_000,
35
- cache: 'volatile',
35
+ cache: "volatile",
36
36
  },
37
37
  },
38
38
  })
@@ -82,7 +82,7 @@ const messages = ctx.timelineMessages()
82
82
  const messages = ctx.timelineMessages({
83
83
  since: 42,
84
84
  projection: (item) => {
85
- if (item.kind === 'run') return [{ role: 'assistant', content: '...' }]
85
+ if (item.kind === "run") return [{ role: "assistant", content: "..." }]
86
86
  return null // use default projection
87
87
  },
88
88
  })
@@ -102,7 +102,7 @@ ctx.useContext({
102
102
  conversation: {
103
103
  content: () => ctx.timelineMessages(),
104
104
  max: 15_000,
105
- cache: 'volatile',
105
+ cache: "volatile",
106
106
  },
107
107
  },
108
108
  })
@@ -117,10 +117,10 @@ Use context entries for information the agent discovers during a run that should
117
117
  ### insertContext
118
118
 
119
119
  ```ts
120
- ctx.insertContext('user-prefs', {
121
- name: 'User preferences',
122
- content: 'Prefers concise responses. Timezone: PST.',
123
- attrs: { priority: 'high' },
120
+ ctx.insertContext("user-prefs", {
121
+ name: "User preferences",
122
+ content: "Prefers concise responses. Timezone: PST.",
123
+ attrs: { priority: "high" },
124
124
  })
125
125
  ```
126
126
 
@@ -129,13 +129,13 @@ Inserting with an existing `id` replaces the previous entry.
129
129
  ### removeContext
130
130
 
131
131
  ```ts
132
- ctx.removeContext('user-prefs')
132
+ ctx.removeContext("user-prefs")
133
133
  ```
134
134
 
135
135
  ### getContext / listContext
136
136
 
137
137
  ```ts
138
- const entry = ctx.getContext('user-prefs')
138
+ const entry = ctx.getContext("user-prefs")
139
139
  // { id: "user-prefs", name: "User preferences", content: "...", insertedAt: 1234 }
140
140
 
141
141
  const all = ctx.listContext()
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Defining entities
3
- titleTemplate: '... - Electric Agents'
3
+ titleTemplate: "... - Electric Agents"
4
4
  description: >-
5
5
  Register entity types with the EntityRegistry, define custom state collections, typed schemas, and handler functions.
6
6
  outline: [2, 3]
@@ -15,16 +15,16 @@ An entity type is registered with an `EntityRegistry`. The registry maps type na
15
15
  `createEntityRegistry()` returns an `EntityRegistry`. Register types with `registry.define(name, definition)`.
16
16
 
17
17
  ```ts
18
- import { createEntityRegistry } from '@electric-ax/agents-runtime'
18
+ import { createEntityRegistry } from "@electric-ax/agents-runtime"
19
19
 
20
20
  const registry = createEntityRegistry()
21
21
 
22
- registry.define('assistant', {
23
- description: 'A general-purpose AI assistant',
22
+ registry.define("assistant", {
23
+ description: "A general-purpose AI assistant",
24
24
  async handler(ctx) {
25
25
  ctx.useAgent({
26
- systemPrompt: 'You are a helpful assistant.',
27
- model: 'claude-sonnet-4-5-20250929',
26
+ systemPrompt: "You are a helpful assistant.",
27
+ model: "claude-sonnet-4-5-20250929",
28
28
  tools: [...ctx.electricTools],
29
29
  })
30
30
  await ctx.agent.run()
@@ -50,15 +50,15 @@ interface EntityDefinition {
50
50
  }
51
51
  ```
52
52
 
53
- | Field | Purpose |
54
- | ---------------- | --------------------------------------------------------------------------------------------------- |
55
- | `description` | Human-readable description. Shown in the Electric Agents UI and CLI. |
53
+ | Field | Purpose |
54
+ | ---------------- | ------------------------------------------------------------------------------------- |
55
+ | `description` | Human-readable description. Shown in the Electric Agents UI and CLI. |
56
56
  | `state` | Custom persistent collections accessed via `ctx.state`, `ctx.db.actions`, and `ctx.db.collections`. |
57
- | `actions` | Factory that returns custom non-CRUD action functions exposed on `ctx.actions`. |
58
- | `creationSchema` | JSON Schema for arguments passed when the entity is spawned. |
59
- | `inboxSchemas` | JSON Schemas for typed inbox message categories. |
60
- | `outputSchemas` | JSON Schemas for typed output message categories. |
61
- | `handler` | The function that runs each time the entity wakes. Required. |
57
+ | `actions` | Factory that returns custom non-CRUD action functions exposed on `ctx.actions`. |
58
+ | `creationSchema` | JSON Schema for arguments passed when the entity is spawned. |
59
+ | `inboxSchemas` | JSON Schemas for typed inbox message categories. |
60
+ | `outputSchemas` | JSON Schemas for typed output message categories. |
61
+ | `handler` | The function that runs each time the entity wakes. Required. |
62
62
 
63
63
  ## Custom state
64
64
 
@@ -81,7 +81,7 @@ interface CollectionDefinition {
81
81
  Declared collections become available via `ctx.state` proxies and the lower-level `ctx.db.actions` / `ctx.db.collections` APIs:
82
82
 
83
83
  ```ts
84
- import { z } from 'zod'
84
+ import { z } from "zod"
85
85
 
86
86
  const childSchema = z.object({
87
87
  key: z.string(),
@@ -89,22 +89,22 @@ const childSchema = z.object({
89
89
  kind: z.string(),
90
90
  })
91
91
 
92
- registry.define('coordinator', {
93
- description: 'Spawns and tracks child entities',
92
+ registry.define("coordinator", {
93
+ description: "Spawns and tracks child entities",
94
94
  state: {
95
- status: { primaryKey: 'key' },
96
- children: { schema: childSchema, primaryKey: 'key' },
95
+ status: { primaryKey: "key" },
96
+ children: { schema: childSchema, primaryKey: "key" },
97
97
  },
98
98
 
99
99
  async handler(ctx) {
100
- if (ctx.firstWake) {
101
- ctx.db.actions.status_insert({ row: { key: 'current', value: 'idle' } })
100
+ if (!ctx.db.collections.status.get("current")) {
101
+ ctx.db.actions.status_insert({ row: { key: "current", value: "idle" } })
102
102
  }
103
103
  // Convenience proxy:
104
104
  ctx.state.children.insert({
105
- key: 'child-1',
106
- url: '/worker/child-1',
107
- kind: 'worker',
105
+ key: "child-1",
106
+ url: "/worker/child-1",
107
+ kind: "worker",
108
108
  })
109
109
 
110
110
  // Lower-level APIs:
@@ -126,9 +126,9 @@ For projects with multiple entity types, keep a separate registry file and impor
126
126
 
127
127
  ```ts
128
128
  // entities/registry.ts
129
- import { createEntityRegistry } from '@electric-ax/agents-runtime'
130
- import { registerAssistant } from './assistant'
131
- import { registerWorker } from './worker'
129
+ import { createEntityRegistry } from "@electric-ax/agents-runtime"
130
+ import { registerAssistant } from "./assistant"
131
+ import { registerWorker } from "./worker"
132
132
 
133
133
  export const registry = createEntityRegistry()
134
134
  registerAssistant(registry)
@@ -137,15 +137,15 @@ registerWorker(registry)
137
137
 
138
138
  ```ts
139
139
  // entities/assistant.ts
140
- import type { EntityRegistry } from '@electric-ax/agents-runtime'
140
+ import type { EntityRegistry } from "@electric-ax/agents-runtime"
141
141
 
142
142
  export function registerAssistant(registry: EntityRegistry) {
143
- registry.define('assistant', {
144
- description: 'General-purpose assistant',
143
+ registry.define("assistant", {
144
+ description: "General-purpose assistant",
145
145
  async handler(ctx) {
146
146
  ctx.useAgent({
147
- systemPrompt: 'You are a helpful assistant.',
148
- model: 'claude-sonnet-4-5-20250929',
147
+ systemPrompt: "You are a helpful assistant.",
148
+ model: "claude-sonnet-4-5-20250929",
149
149
  tools: [...ctx.electricTools],
150
150
  })
151
151
  await ctx.agent.run()
@@ -161,12 +161,12 @@ This keeps each entity type isolated and the registry composition explicit.
161
161
  `creationSchema`, `inboxSchemas`, and `outputSchemas` accept [`StandardJSONSchemaV1`](https://github.com/standard-schema/standard-schema) objects. Any schema library implementing the Standard JSON Schema interface works (e.g. Zod v4). These schemas are used for validation and for generating UI and documentation in the Electric Agents dashboard.
162
162
 
163
163
  ```ts
164
- import { z } from 'zod/v4'
164
+ import { z } from "zod/v4"
165
165
 
166
- registry.define('processor', {
167
- description: 'Processes structured tasks',
166
+ registry.define("processor", {
167
+ description: "Processes structured tasks",
168
168
  creationSchema: z.object({
169
- priority: z.enum(['low', 'medium', 'high']).default('medium'),
169
+ priority: z.enum(["low", "medium", "high"]).default("medium"),
170
170
  }),
171
171
  inboxSchemas: {
172
172
  task: z.object({