@electric-ax/agents 0.2.1 → 0.2.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.
Files changed (49) hide show
  1. package/dist/entrypoint.js +5 -3
  2. package/dist/index.cjs +5 -3
  3. package/dist/index.js +5 -3
  4. package/docs/entities/agents/horton.md +89 -0
  5. package/docs/entities/agents/worker.md +102 -0
  6. package/docs/entities/patterns/blackboard.md +111 -0
  7. package/docs/entities/patterns/dispatcher.md +77 -0
  8. package/docs/entities/patterns/manager-worker.md +127 -0
  9. package/docs/entities/patterns/map-reduce.md +81 -0
  10. package/docs/entities/patterns/pipeline.md +101 -0
  11. package/docs/entities/patterns/reactive-observers.md +125 -0
  12. package/docs/examples/mega-draw.md +106 -0
  13. package/docs/examples/playground.md +46 -0
  14. package/docs/index.md +208 -0
  15. package/docs/quickstart.md +201 -0
  16. package/docs/reference/agent-config.md +82 -0
  17. package/docs/reference/agent-tool.md +58 -0
  18. package/docs/reference/built-in-collections.md +334 -0
  19. package/docs/reference/cli.md +238 -0
  20. package/docs/reference/entity-definition.md +57 -0
  21. package/docs/reference/entity-handle.md +63 -0
  22. package/docs/reference/entity-registry.md +73 -0
  23. package/docs/reference/handler-context.md +108 -0
  24. package/docs/reference/runtime-handler.md +136 -0
  25. package/docs/reference/shared-state-handle.md +74 -0
  26. package/docs/reference/state-collection-proxy.md +41 -0
  27. package/docs/reference/wake-event.md +132 -0
  28. package/docs/usage/app-setup.md +165 -0
  29. package/docs/usage/clients-and-react.md +191 -0
  30. package/docs/usage/configuring-the-agent.md +136 -0
  31. package/docs/usage/context-composition.md +204 -0
  32. package/docs/usage/defining-entities.md +181 -0
  33. package/docs/usage/defining-tools.md +229 -0
  34. package/docs/usage/embedded-builtins.md +180 -0
  35. package/docs/usage/managing-state.md +93 -0
  36. package/docs/usage/overview.md +284 -0
  37. package/docs/usage/programmatic-runtime-client.md +216 -0
  38. package/docs/usage/shared-state.md +169 -0
  39. package/docs/usage/spawning-and-coordinating.md +165 -0
  40. package/docs/usage/testing.md +76 -0
  41. package/docs/usage/waking-entities.md +148 -0
  42. package/docs/usage/writing-handlers.md +267 -0
  43. package/package.json +2 -1
  44. package/skills/quickstart/scaffold/package.json +16 -3
  45. package/skills/quickstart/scaffold/tsconfig.json +8 -3
  46. package/skills/quickstart/scaffold/vite.config.ts +21 -0
  47. package/skills/quickstart/scaffold-ui/index.html +12 -0
  48. package/skills/quickstart/scaffold-ui/main.tsx +235 -0
  49. package/skills/quickstart.md +244 -334
@@ -0,0 +1,201 @@
1
+ ---
2
+ title: Quickstart
3
+ titleTemplate: '... - Electric Agents'
4
+ description: >-
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
+ outline: [2, 3]
7
+ ---
8
+
9
+ # Quickstart
10
+
11
+ One command starts the Electric Agents runtime, the web UI, and a local [Horton](./entities/agents/horton) assistant you can chat with right away. From there, define your own [entities](./usage/defining-entities) in your own app.
12
+
13
+ ```sh
14
+ npx electric-ax agents quickstart
15
+ ```
16
+
17
+ ## What you'll need
18
+
19
+ - **Node.js 18+**.
20
+ - **[Docker](https://docs.docker.com/get-docker/)**. The runtime server, Postgres, and Electric run as containers.
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.
23
+
24
+ ## Set your API key
25
+
26
+ Either export it in your shell:
27
+
28
+ ```sh
29
+ export ANTHROPIC_API_KEY=sk-ant-...
30
+ ```
31
+
32
+ Or persist it in a `.env` file in the directory you run the CLI from (this creates or overwrites `.env` in the current directory):
33
+
34
+ ```sh
35
+ cat <<'EOF' > .env
36
+ ANTHROPIC_API_KEY=sk-ant-...
37
+ # BRAVE_SEARCH_API_KEY=BS...
38
+ EOF
39
+ ```
40
+
41
+ The CLI also accepts `--anthropic-api-key <key>` if you'd rather pass it inline.
42
+
43
+ ## Start the runtime
44
+
45
+ ```sh
46
+ npx electric-ax agents quickstart
47
+ ```
48
+
49
+ This:
50
+
51
+ 1. Starts Postgres, Electric, and the Electric Agents runtime server in Docker (the runtime serves both the API and the web UI on `http://localhost:4437`).
52
+ 2. Starts a built-in **Horton** runtime in the foreground that registers the `horton` and `worker` entity types.
53
+ 3. Prints onboarding commands you can copy into a second terminal.
54
+
55
+ Leave this terminal running. Press `Ctrl-C` to stop the built-in Horton runtime — the runtime server containers keep running in the background until you call [`electric agents stop`](#stop-the-dev-environment).
56
+
57
+ ## Chat with Horton
58
+
59
+ ### From the web UI
60
+
61
+ Open [http://localhost:4437](http://localhost:4437). Spawn a `horton` entity from the dashboard and send it a message — its timeline updates live as the agent thinks, calls tools, and responds.
62
+
63
+ ### From the CLI
64
+
65
+ In a separate terminal:
66
+
67
+ ```sh
68
+ npx electric-ax agents spawn /horton/onboarding
69
+ npx electric-ax agents send /horton/onboarding 'Walk me through Electric Agents'
70
+ npx electric-ax agents observe /horton/onboarding
71
+ ```
72
+
73
+ - `spawn` creates a new entity instance at the given path.
74
+ - `send` delivers a message to the entity's inbox, waking its handler.
75
+ - `observe` streams the entity's events to your terminal in real time, with reasoning, tool calls, and text deltas rendered inline.
76
+
77
+ See the [CLI reference](./reference/cli) for the full command surface.
78
+
79
+ ## Define your own entity types
80
+
81
+ Once you're chatting with Horton, the next step is to define your own entity types in your own app. Your app is just a process that registers entity types with the runtime server and receives webhook callbacks when they wake.
82
+
83
+ ### 1. Install the runtime SDK
84
+
85
+ ```sh
86
+ mkdir my-agents-app && cd my-agents-app
87
+ npm init -y
88
+ npm install @electric-ax/agents-runtime
89
+ npm install --save-dev tsx
90
+ ```
91
+
92
+ ### 2. Create a server
93
+
94
+ Create `server.ts`:
95
+
96
+ ```ts
97
+ import http from 'node:http'
98
+ import {
99
+ createEntityRegistry,
100
+ createRuntimeHandler,
101
+ } from '@electric-ax/agents-runtime'
102
+
103
+ const ELECTRIC_AGENTS_URL =
104
+ process.env.ELECTRIC_AGENTS_URL ?? 'http://localhost:4437'
105
+ const PORT = Number(process.env.PORT ?? 3000)
106
+ const SERVE_URL = process.env.SERVE_URL ?? `http://localhost:${PORT}`
107
+
108
+ const registry = createEntityRegistry()
109
+
110
+ registry.define('assistant', {
111
+ description: 'A general-purpose AI assistant',
112
+ async handler(ctx) {
113
+ ctx.useAgent({
114
+ systemPrompt: 'You are a helpful assistant.',
115
+ model: 'claude-sonnet-4-5-20250929',
116
+ tools: [...ctx.electricTools],
117
+ })
118
+ await ctx.agent.run()
119
+ },
120
+ })
121
+
122
+ const runtime = createRuntimeHandler({
123
+ baseUrl: ELECTRIC_AGENTS_URL,
124
+ serveEndpoint: `${SERVE_URL}/webhook`,
125
+ registry,
126
+ })
127
+
128
+ const server = http.createServer(async (req, res) => {
129
+ if (req.url === '/webhook' && req.method === 'POST') {
130
+ await runtime.onEnter(req, res)
131
+ return
132
+ }
133
+ res.writeHead(404)
134
+ res.end()
135
+ })
136
+
137
+ server.listen(PORT, async () => {
138
+ await runtime.registerTypes()
139
+ console.log(`App server ready on port ${PORT}`)
140
+ })
141
+ ```
142
+
143
+ This does four things:
144
+
145
+ 1. **Defines an entity type** called `assistant` with a handler that configures and runs an LLM agent.
146
+ 2. **Creates a runtime handler** that connects to the runtime server.
147
+ 3. **Starts an HTTP server** to receive webhook callbacks from the runtime.
148
+ 4. **Registers entity types** with the runtime server on startup.
149
+
150
+ See [App setup](./usage/app-setup) for the full `createRuntimeHandler` configuration.
151
+
152
+ ### 3. Run your app
153
+
154
+ With the runtime server already running (from `electric agents quickstart` or `electric agents start`), start your app:
155
+
156
+ ```sh
157
+ npx tsx server.ts
158
+ ```
159
+
160
+ Your handler calls `ctx.useAgent()` in this process, so make sure `ANTHROPIC_API_KEY` is exported in this shell (or copy your `.env` into `my-agents-app`).
161
+
162
+ ### 4. Interact with your entity
163
+
164
+ Spawn an instance, send it a message, and observe the timeline:
165
+
166
+ ```sh
167
+ npx electric-ax agents spawn /assistant/my-assistant
168
+ npx electric-ax agents send /assistant/my-assistant 'Hello!'
169
+ npx electric-ax agents observe /assistant/my-assistant
170
+ ```
171
+
172
+ Or open the web UI at `http://localhost:4437` and pick `/assistant/my-assistant` from the entity list.
173
+
174
+ ## Stop the dev environment
175
+
176
+ `Ctrl-C` in the quickstart terminal stops the built-in Horton runtime. The runtime server containers keep running. To stop them:
177
+
178
+ ```sh
179
+ npx electric-ax agents stop # stop containers, keep data
180
+ npx electric-ax agents stop --remove-volumes # stop containers and wipe data
181
+ ```
182
+
183
+ ## Run pieces independently
184
+
185
+ `quickstart` runs `start` then `start-builtin` for you. Run them yourself if you want the runtime server up across multiple sessions, or to run your own agent process instead of the built-ins:
186
+
187
+ ```sh
188
+ npx electric-ax agents start # runtime server + UI (background, Docker)
189
+ npx electric-ax agents start-builtin # built-in Horton + worker (foreground)
190
+ ```
191
+
192
+ See the [CLI reference](./reference/cli#start) for the full set of commands.
193
+
194
+ ## Next steps
195
+
196
+ - [Overview](./) — the mental model behind entities, handlers, and wakes.
197
+ - [Usage overview](./usage/overview) — the full developer surface on one page.
198
+ - [Defining entities](./usage/defining-entities) — entity types, schemas, and configuration.
199
+ - [Writing handlers](./usage/writing-handlers) — handler lifecycle and the `ctx` API.
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.
@@ -0,0 +1,82 @@
1
+ ---
2
+ title: AgentConfig
3
+ titleTemplate: '... - Electric Agents'
4
+ description: >-
5
+ API reference for AgentConfig: system prompt, model, tools, streaming, and test responses.
6
+ outline: [2, 3]
7
+ ---
8
+
9
+ # AgentConfig
10
+
11
+ Configuration for the LLM agent loop. Passed to `ctx.useAgent()`.
12
+
13
+ **Source:** `@electric-ax/agents-runtime`
14
+
15
+ ```ts
16
+ interface AgentConfig {
17
+ systemPrompt: string
18
+ model: string | Model<any>
19
+ provider?: KnownProvider
20
+ tools: AgentTool[]
21
+ streamFn?: StreamFn
22
+ testResponses?: string[] | TestResponseFn
23
+ }
24
+ ```
25
+
26
+ ## Fields
27
+
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"`. |
33
+ | `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. |
36
+
37
+ ## TestResponseFn
38
+
39
+ ```ts
40
+ type TestResponseFn = (
41
+ message: string,
42
+ bridge: OutboundBridgeHandle
43
+ ) => Promise<string | undefined>
44
+ ```
45
+
46
+ A function that receives the current trigger message and an outbound bridge, then returns a mock response string. Returning `undefined` emits no automatic text response.
47
+
48
+ ## AgentHandle
49
+
50
+ Returned by `ctx.useAgent()`. Also available as `ctx.agent`.
51
+
52
+ ```ts
53
+ interface AgentHandle {
54
+ run(input?: string): Promise<AgentRunResult>
55
+ }
56
+ ```
57
+
58
+ | Method | Return Type | Description |
59
+ | ------------- | ------------------------- | ---------------------------------------------------------------------------- |
60
+ | `run(input?)` | `Promise<AgentRunResult>` | Execute the agent loop. Runs until the LLM stops or all tool calls complete. |
61
+
62
+ **Parameters:**
63
+
64
+ | Parameter | Type | Required | Description |
65
+ | --------- | -------- | -------- | -------------------------------------------------------------------------------- |
66
+ | `input` | `string` | No | Optional user message appended to the conversation before the agent loop starts. |
67
+
68
+ ## AgentRunResult
69
+
70
+ ```ts
71
+ interface AgentRunResult {
72
+ writes: ChangeEvent[]
73
+ toolCalls: Array<{ name: string; args: unknown; result: unknown }>
74
+ usage: { tokens: number; duration: number }
75
+ }
76
+ ```
77
+
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. |
82
+ | `usage` | `{ tokens: number; duration: number }` | Currently returned as `{ tokens: 0, duration: 0 }` until usage aggregation is wired in. |
@@ -0,0 +1,58 @@
1
+ ---
2
+ title: AgentTool
3
+ titleTemplate: '... - Electric Agents'
4
+ description: >-
5
+ Interface reference for AgentTool: name, description, TypeBox parameters schema, and execute function.
6
+ outline: [2, 3]
7
+ ---
8
+
9
+ # AgentTool
10
+
11
+ Interface for tools the LLM can call during the agent loop. Re-exported from [`@mariozechner/pi-agent-core`](https://github.com/badlogic/pi-mono).
12
+
13
+ **Source:** `@electric-ax/agents-runtime` (re-export)
14
+
15
+ ```ts
16
+ interface AgentTool<TParameters extends TSchema = TSchema, TDetails = any> {
17
+ name: string
18
+ label: string
19
+ description: string
20
+ parameters: TParameters
21
+ execute: (
22
+ toolCallId: string,
23
+ params: Static<TParameters>,
24
+ signal?: AbortSignal,
25
+ onUpdate?: AgentToolUpdateCallback<TDetails>
26
+ ) => Promise<AgentToolResult<TDetails>>
27
+ }
28
+ ```
29
+
30
+ ## Fields
31
+
32
+ | Field | Type | Required | Description |
33
+ | ------------- | ---------------------------------------------------------------------- | -------- | -------------------------------------------------------------------- |
34
+ | `name` | `string` | Yes | Unique tool name used in LLM function calling. |
35
+ | `label` | `string` | Yes | Human-readable label for display. |
36
+ | `description` | `string` | Yes | Description sent to the LLM to explain when and how to use the tool. |
37
+ | `parameters` | `TSchema` | Yes | TypeBox JSON Schema defining the tool's parameters. |
38
+ | `execute` | `(toolCallId, params, signal?, onUpdate?) => Promise<AgentToolResult>` | Yes | Function called when the LLM invokes the tool. |
39
+
40
+ Parameters are defined using [TypeBox](https://github.com/sinclairzx81/typebox) (`@sinclair/typebox`). The schema is used for LLM function calling and argument validation.
41
+
42
+ ## AgentToolResult
43
+
44
+ ```ts
45
+ interface AgentToolResult<T = any> {
46
+ content: (TextContent | ImageContent)[]
47
+ details: T
48
+ }
49
+ ```
50
+
51
+ | Field | Type | Description |
52
+ | --------- | --------------------------------- | ------------------------------------------------------------------------ |
53
+ | `content` | `(TextContent \| ImageContent)[]` | Content returned to the LLM. Typically `{ type: 'text', text: string }`. |
54
+ | `details` | `T` | Arbitrary metadata. Must be provided (use `{}` if no details). |
55
+
56
+ ::: warning
57
+ Every tool must return a `details` property. Omitting it causes a type error.
58
+ :::
@@ -0,0 +1,334 @@
1
+ ---
2
+ title: Built-in collections
3
+ titleTemplate: '... - Electric Agents'
4
+ description: >-
5
+ Reference for the 17 runtime-managed collections: runs, steps, texts, toolCalls, inbox, errors, and more.
6
+ outline: [2, 3]
7
+ ---
8
+
9
+ # Built-in collections
10
+
11
+ Every entity automatically has these 17 collections, populated by the runtime as the agent operates. Custom state collections defined in `EntityDefinition.state` are merged with these at creation time.
12
+
13
+ **Source:** `@electric-ax/agents-runtime` -- `entity-schema.ts`
14
+
15
+ ## Collection summary
16
+
17
+ | Collection | Event Type | Interface | Description |
18
+ | ------------------ | ------------------ | ------------------ | ---------------------------- |
19
+ | `runs` | `run` | `Run` | Agent run lifecycle |
20
+ | `steps` | `step` | `Step` | LLM call step lifecycle |
21
+ | `texts` | `text` | `Text` | Text message lifecycle |
22
+ | `textDeltas` | `text_delta` | `TextDelta` | Incremental text content |
23
+ | `toolCalls` | `tool_call` | `ToolCall` | Tool call lifecycle |
24
+ | `reasoning` | `reasoning` | `Reasoning` | Reasoning block lifecycle |
25
+ | `errors` | `error` | `ErrorEvent` | Diagnostic errors |
26
+ | `inbox` | `message_received` | `MessageReceived` | Inbound messages |
27
+ | `wakes` | `wake` | `WakeEntry` | Wake delivery records |
28
+ | `entityCreated` | `entity_created` | `EntityCreated` | Entity bootstrap metadata |
29
+ | `entityStopped` | `entity_stopped` | `EntityStopped` | Entity shutdown signal |
30
+ | `childStatus` | `child_status` | `ChildStatusEntry` | Child/observed entity status |
31
+ | `tags` | `tags` | `TagEntry` | Entity tags |
32
+ | `contextInserted` | `context_inserted` | `ContextInserted` | Context additions |
33
+ | `contextRemoved` | `context_removed` | `ContextRemoved` | Context removals |
34
+ | `manifests` | `manifest` | `Manifest` | Durable resource manifests |
35
+ | `replayWatermarks` | `replay_watermark` | `ReplayWatermark` | Replay progress tracking |
36
+
37
+ All collections use `key` as the primary key.
38
+
39
+ ## Type definitions
40
+
41
+ ### Run
42
+
43
+ ```ts
44
+ interface Run {
45
+ key: string
46
+ status: 'started' | 'completed' | 'failed'
47
+ finish_reason?: string
48
+ }
49
+ ```
50
+
51
+ ### Step
52
+
53
+ ```ts
54
+ interface Step {
55
+ key: string
56
+ run_id?: string
57
+ step_number: number
58
+ status: 'started' | 'completed'
59
+ finish_reason?: string
60
+ model_provider?: string
61
+ model_id?: string
62
+ duration_ms?: number
63
+ }
64
+ ```
65
+
66
+ ### Text
67
+
68
+ ```ts
69
+ interface Text {
70
+ key: string
71
+ run_id?: string
72
+ status: 'streaming' | 'completed'
73
+ }
74
+ ```
75
+
76
+ ### TextDelta
77
+
78
+ ```ts
79
+ interface TextDelta {
80
+ key: string
81
+ text_id: string
82
+ run_id: string
83
+ delta: string
84
+ }
85
+ ```
86
+
87
+ ### ToolCall
88
+
89
+ ```ts
90
+ interface ToolCall {
91
+ key: string
92
+ run_id?: string
93
+ tool_name: string
94
+ status: 'started' | 'args_complete' | 'executing' | 'completed' | 'failed'
95
+ args?: unknown
96
+ result?: unknown
97
+ error?: string
98
+ duration_ms?: number
99
+ }
100
+ ```
101
+
102
+ ### Reasoning
103
+
104
+ ```ts
105
+ interface Reasoning {
106
+ key: string
107
+ status: 'streaming' | 'completed'
108
+ }
109
+ ```
110
+
111
+ ### ErrorEvent
112
+
113
+ ```ts
114
+ interface ErrorEvent {
115
+ key: string
116
+ error_code: string
117
+ message: string
118
+ run_id?: string
119
+ step_id?: string
120
+ tool_call_id?: string
121
+ }
122
+ ```
123
+
124
+ ### MessageReceived
125
+
126
+ ```ts
127
+ interface MessageReceived {
128
+ key: string
129
+ from: string
130
+ payload?: unknown
131
+ timestamp: string
132
+ message_type?: string
133
+ }
134
+ ```
135
+
136
+ ### WakeEntry
137
+
138
+ ```ts
139
+ interface WakeEntry {
140
+ key: string
141
+ timestamp: string
142
+ source: string
143
+ timeout: boolean
144
+ changes: WakeChangeEntry[]
145
+ finished_child?: WakeFinishedChildEntry
146
+ other_children?: WakeOtherChildEntry[]
147
+ }
148
+
149
+ interface WakeChangeEntry {
150
+ collection: string
151
+ kind: 'insert' | 'update' | 'delete'
152
+ key: string
153
+ }
154
+
155
+ interface WakeFinishedChildEntry {
156
+ url: string
157
+ type: string
158
+ run_status: 'completed' | 'failed'
159
+ response?: string // concatenated text deltas from the finished run
160
+ error?: string // error message(s) if run_status is "failed"
161
+ }
162
+
163
+ interface WakeOtherChildEntry {
164
+ url: string
165
+ type: string
166
+ status: 'spawning' | 'running' | 'idle' | 'stopped'
167
+ }
168
+ ```
169
+
170
+ ### EntityCreated
171
+
172
+ ```ts
173
+ interface EntityCreated {
174
+ key: string
175
+ entity_type: string
176
+ timestamp: string
177
+ args: Record<string, JsonValue>
178
+ parent_url?: string
179
+ }
180
+ ```
181
+
182
+ ### EntityStopped
183
+
184
+ ```ts
185
+ interface EntityStopped {
186
+ key: string
187
+ timestamp: string
188
+ reason?: string
189
+ }
190
+ ```
191
+
192
+ ### ChildStatusEntry
193
+
194
+ ```ts
195
+ interface ChildStatusEntry {
196
+ key: string
197
+ entity_url: string
198
+ entity_type: string
199
+ status: 'spawning' | 'running' | 'idle' | 'stopped'
200
+ }
201
+ ```
202
+
203
+ ### TagEntry
204
+
205
+ ```ts
206
+ interface TagEntry {
207
+ key: string
208
+ value: string
209
+ }
210
+ ```
211
+
212
+ ### ContextInserted
213
+
214
+ ```ts
215
+ interface ContextInserted {
216
+ key: string
217
+ id: string
218
+ name: string
219
+ attrs: Record<string, string | number | boolean>
220
+ content: string
221
+ timestamp: string
222
+ }
223
+ ```
224
+
225
+ ### ContextRemoved
226
+
227
+ ```ts
228
+ interface ContextRemoved {
229
+ key: string
230
+ id: string
231
+ name: string
232
+ timestamp: string
233
+ }
234
+ ```
235
+
236
+ ### Manifest
237
+
238
+ Discriminated union by `kind`:
239
+
240
+ ```ts
241
+ type Manifest =
242
+ | ManifestChildEntry
243
+ | ManifestSourceEntry
244
+ | ManifestSharedStateEntry
245
+ | ManifestEffectEntry
246
+ | ManifestContextEntry
247
+ | ManifestCronScheduleEntry
248
+ | ManifestFutureSendScheduleEntry
249
+
250
+ interface ManifestChildEntry {
251
+ key: string
252
+ kind: 'child'
253
+ id: string
254
+ entity_type: string
255
+ entity_url: string
256
+ wake?: WakeConfig
257
+ observed: boolean
258
+ }
259
+
260
+ interface ManifestSourceEntry {
261
+ key: string
262
+ kind: 'source'
263
+ sourceType: string
264
+ sourceRef: string
265
+ wake?: WakeConfig
266
+ config: Record<string, unknown>
267
+ }
268
+
269
+ interface ManifestSharedStateEntry {
270
+ key: string
271
+ kind: 'shared-state'
272
+ id: string
273
+ mode: 'create' | 'connect'
274
+ collections: Record<string, { type: string; primaryKey: string }>
275
+ wake?: WakeConfig
276
+ }
277
+
278
+ interface ManifestEffectEntry {
279
+ key: string
280
+ kind: 'effect'
281
+ id: string
282
+ function_ref: string
283
+ config: unknown
284
+ }
285
+
286
+ interface ManifestContextEntry {
287
+ key: string
288
+ kind: 'context'
289
+ id: string
290
+ name: string
291
+ attrs: Record<string, string | number | boolean>
292
+ content: string
293
+ insertedAt: number
294
+ }
295
+
296
+ interface ManifestCronScheduleEntry {
297
+ key: string
298
+ kind: 'schedule'
299
+ id: string
300
+ scheduleType: 'cron'
301
+ expression: string
302
+ timezone?: string
303
+ payload?: unknown
304
+ wake?: WakeConfig
305
+ }
306
+
307
+ interface ManifestFutureSendScheduleEntry {
308
+ key: string
309
+ kind: 'schedule'
310
+ id: string
311
+ scheduleType: 'future_send'
312
+ fireAt: string
313
+ targetUrl: string
314
+ payload: unknown
315
+ producerId: string
316
+ from?: string
317
+ messageType?: string
318
+ status?: 'pending' | 'sent' | 'failed'
319
+ sentAt?: string
320
+ failedAt?: string
321
+ lastError?: string
322
+ }
323
+ ```
324
+
325
+ ### ReplayWatermark
326
+
327
+ ```ts
328
+ interface ReplayWatermark {
329
+ key: string
330
+ source_id: string
331
+ offset: string
332
+ updated_at: string
333
+ }
334
+ ```