klaus-agent 0.1.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 (163) hide show
  1. package/README.md +685 -0
  2. package/dist/approval/approval.d.ts +18 -0
  3. package/dist/approval/approval.js +93 -0
  4. package/dist/approval/approval.js.map +1 -0
  5. package/dist/approval/types.d.ts +21 -0
  6. package/dist/approval/types.js +3 -0
  7. package/dist/approval/types.js.map +1 -0
  8. package/dist/background/task-manager.d.ts +14 -0
  9. package/dist/background/task-manager.js +89 -0
  10. package/dist/background/task-manager.js.map +1 -0
  11. package/dist/background/tools.d.ts +4 -0
  12. package/dist/background/tools.js +74 -0
  13. package/dist/background/tools.js.map +1 -0
  14. package/dist/background/types.d.ts +31 -0
  15. package/dist/background/types.js +3 -0
  16. package/dist/background/types.js.map +1 -0
  17. package/dist/checkpoint/checkpoint-manager.d.ts +19 -0
  18. package/dist/checkpoint/checkpoint-manager.js +49 -0
  19. package/dist/checkpoint/checkpoint-manager.js.map +1 -0
  20. package/dist/checkpoint/dmail.d.ts +10 -0
  21. package/dist/checkpoint/dmail.js +26 -0
  22. package/dist/checkpoint/dmail.js.map +1 -0
  23. package/dist/checkpoint/types.d.ts +12 -0
  24. package/dist/checkpoint/types.js +3 -0
  25. package/dist/checkpoint/types.js.map +1 -0
  26. package/dist/compaction/compaction.d.ts +6 -0
  27. package/dist/compaction/compaction.js +104 -0
  28. package/dist/compaction/compaction.js.map +1 -0
  29. package/dist/compaction/summarizer.d.ts +10 -0
  30. package/dist/compaction/summarizer.js +75 -0
  31. package/dist/compaction/summarizer.js.map +1 -0
  32. package/dist/compaction/types.d.ts +23 -0
  33. package/dist/compaction/types.js +3 -0
  34. package/dist/compaction/types.js.map +1 -0
  35. package/dist/core/agent-loop.d.ts +37 -0
  36. package/dist/core/agent-loop.js +337 -0
  37. package/dist/core/agent-loop.js.map +1 -0
  38. package/dist/core/agent.d.ts +97 -0
  39. package/dist/core/agent.js +335 -0
  40. package/dist/core/agent.js.map +1 -0
  41. package/dist/extensions/runner.d.ts +19 -0
  42. package/dist/extensions/runner.js +88 -0
  43. package/dist/extensions/runner.js.map +1 -0
  44. package/dist/extensions/types.d.ts +179 -0
  45. package/dist/extensions/types.js +3 -0
  46. package/dist/extensions/types.js.map +1 -0
  47. package/dist/index.d.ts +78 -0
  48. package/dist/index.js +53 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/injection/history-normalizer.d.ts +2 -0
  51. package/dist/injection/history-normalizer.js +34 -0
  52. package/dist/injection/history-normalizer.js.map +1 -0
  53. package/dist/injection/injection-manager.d.ts +8 -0
  54. package/dist/injection/injection-manager.js +28 -0
  55. package/dist/injection/injection-manager.js.map +1 -0
  56. package/dist/injection/types.d.ts +8 -0
  57. package/dist/injection/types.js +3 -0
  58. package/dist/injection/types.js.map +1 -0
  59. package/dist/llm/provider.d.ts +16 -0
  60. package/dist/llm/provider.js +233 -0
  61. package/dist/llm/provider.js.map +1 -0
  62. package/dist/llm/types.d.ts +110 -0
  63. package/dist/llm/types.js +3 -0
  64. package/dist/llm/types.js.map +1 -0
  65. package/dist/multi-agent/labor-market.d.ts +16 -0
  66. package/dist/multi-agent/labor-market.js +40 -0
  67. package/dist/multi-agent/labor-market.js.map +1 -0
  68. package/dist/multi-agent/task-executor.d.ts +12 -0
  69. package/dist/multi-agent/task-executor.js +38 -0
  70. package/dist/multi-agent/task-executor.js.map +1 -0
  71. package/dist/multi-agent/task-tool.d.ts +4 -0
  72. package/dist/multi-agent/task-tool.js +46 -0
  73. package/dist/multi-agent/task-tool.js.map +1 -0
  74. package/dist/multi-agent/types.d.ts +7 -0
  75. package/dist/multi-agent/types.js +3 -0
  76. package/dist/multi-agent/types.js.map +1 -0
  77. package/dist/session/session-context-builder.d.ts +2 -0
  78. package/dist/session/session-context-builder.js +52 -0
  79. package/dist/session/session-context-builder.js.map +1 -0
  80. package/dist/session/session-manager.d.ts +30 -0
  81. package/dist/session/session-manager.js +209 -0
  82. package/dist/session/session-manager.js.map +1 -0
  83. package/dist/session/types.d.ts +61 -0
  84. package/dist/session/types.js +3 -0
  85. package/dist/session/types.js.map +1 -0
  86. package/dist/skills/discovery.d.ts +2 -0
  87. package/dist/skills/discovery.js +29 -0
  88. package/dist/skills/discovery.js.map +1 -0
  89. package/dist/skills/loader.d.ts +3 -0
  90. package/dist/skills/loader.js +46 -0
  91. package/dist/skills/loader.js.map +1 -0
  92. package/dist/skills/skill-tool.d.ts +3 -0
  93. package/dist/skills/skill-tool.js +38 -0
  94. package/dist/skills/skill-tool.js.map +1 -0
  95. package/dist/skills/types.d.ts +14 -0
  96. package/dist/skills/types.js +3 -0
  97. package/dist/skills/types.js.map +1 -0
  98. package/dist/tools/executor.d.ts +37 -0
  99. package/dist/tools/executor.js +131 -0
  100. package/dist/tools/executor.js.map +1 -0
  101. package/dist/tools/mcp-adapter.d.ts +57 -0
  102. package/dist/tools/mcp-adapter.js +113 -0
  103. package/dist/tools/mcp-adapter.js.map +1 -0
  104. package/dist/tools/types.d.ts +43 -0
  105. package/dist/tools/types.js +2 -0
  106. package/dist/tools/types.js.map +1 -0
  107. package/dist/types.d.ts +96 -0
  108. package/dist/types.js +3 -0
  109. package/dist/types.js.map +1 -0
  110. package/dist/utils/id.d.ts +1 -0
  111. package/dist/utils/id.js +9 -0
  112. package/dist/utils/id.js.map +1 -0
  113. package/dist/utils/jsonl.d.ts +3 -0
  114. package/dist/utils/jsonl.js +17 -0
  115. package/dist/utils/jsonl.js.map +1 -0
  116. package/dist/wire/types.d.ts +10 -0
  117. package/dist/wire/types.js +3 -0
  118. package/dist/wire/types.js.map +1 -0
  119. package/dist/wire/wire.d.ts +20 -0
  120. package/dist/wire/wire.js +71 -0
  121. package/dist/wire/wire.js.map +1 -0
  122. package/package.json +26 -0
  123. package/src/approval/approval.ts +108 -0
  124. package/src/approval/types.ts +26 -0
  125. package/src/background/task-manager.ts +112 -0
  126. package/src/background/tools.ts +84 -0
  127. package/src/background/types.ts +29 -0
  128. package/src/checkpoint/checkpoint-manager.ts +60 -0
  129. package/src/checkpoint/dmail.ts +35 -0
  130. package/src/checkpoint/types.ts +16 -0
  131. package/src/compaction/compaction.ts +119 -0
  132. package/src/compaction/summarizer.ts +83 -0
  133. package/src/compaction/types.ts +29 -0
  134. package/src/core/agent-loop.ts +427 -0
  135. package/src/core/agent.ts +430 -0
  136. package/src/extensions/runner.ts +138 -0
  137. package/src/extensions/types.ts +177 -0
  138. package/src/index.ts +221 -0
  139. package/src/injection/history-normalizer.ts +44 -0
  140. package/src/injection/injection-manager.ts +34 -0
  141. package/src/injection/types.ts +12 -0
  142. package/src/llm/provider.ts +254 -0
  143. package/src/llm/types.ts +146 -0
  144. package/src/multi-agent/labor-market.ts +54 -0
  145. package/src/multi-agent/task-executor.ts +49 -0
  146. package/src/multi-agent/task-tool.ts +58 -0
  147. package/src/multi-agent/types.ts +10 -0
  148. package/src/session/session-context-builder.ts +65 -0
  149. package/src/session/session-manager.ts +258 -0
  150. package/src/session/types.ts +93 -0
  151. package/src/skills/discovery.ts +32 -0
  152. package/src/skills/loader.ts +54 -0
  153. package/src/skills/skill-tool.ts +50 -0
  154. package/src/skills/types.ts +18 -0
  155. package/src/tools/executor.ts +196 -0
  156. package/src/tools/mcp-adapter.ts +185 -0
  157. package/src/tools/types.ts +64 -0
  158. package/src/types.ts +96 -0
  159. package/src/utils/id.ts +8 -0
  160. package/src/utils/jsonl.ts +19 -0
  161. package/src/wire/types.ts +14 -0
  162. package/src/wire/wire.ts +79 -0
  163. package/tsconfig.json +19 -0
package/README.md ADDED
@@ -0,0 +1,685 @@
1
+ # @klaus-ai/agent
2
+
3
+ Universal agent framework SDK. Inject tools, skills, and systemPrompt to build your agent — no wrapper needed.
4
+
5
+ 通用 Agent 框架 SDK。注入 tools、skills、systemPrompt 即可构建 agent,无需再包一层。
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @klaus-ai/agent
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { createAgent } from "@klaus-ai/agent";
17
+ import { Type } from "@sinclair/typebox";
18
+
19
+ const agent = createAgent({
20
+ model: { provider: "anthropic", model: "claude-sonnet-4-20250514", maxContextTokens: 200000 },
21
+ systemPrompt: "You are a helpful assistant.",
22
+ tools: [
23
+ {
24
+ name: "echo",
25
+ label: "Echo",
26
+ description: "Echo back the input",
27
+ parameters: Type.Object({ text: Type.String() }),
28
+ async execute(_id, params) {
29
+ return { content: [{ type: "text", text: params.text }] };
30
+ },
31
+ },
32
+ ],
33
+ approval: { yolo: true },
34
+ });
35
+
36
+ // Subscribe to streaming events
37
+ agent.subscribe((event) => {
38
+ if (event.type === "message_update" && event.event.type === "text") {
39
+ process.stdout.write(event.event.text);
40
+ }
41
+ });
42
+
43
+ const messages = await agent.prompt("Say hello");
44
+ ```
45
+
46
+ ## Architecture
47
+
48
+ Single package, 14 modules, zero wrappers. All capabilities are built-in and opt-in via config.
49
+
50
+ 单包架构,14 个模块,零包装层。所有能力内置,通过 config 按需启用。
51
+
52
+ ```
53
+ src/
54
+ ├── core/ Agent + AgentLoop (nested dual-loop runtime)
55
+ ├── llm/ Provider abstraction + Anthropic implementation
56
+ ├── tools/ Tool executor (sequential/parallel) + MCP adapter
57
+ ├── approval/ Queue-based approval system
58
+ ├── session/ JSONL tree persistence with branching
59
+ ├── compaction/ Token estimation + LLM summarization
60
+ ├── checkpoint/ Checkpoint + D-Mail time travel
61
+ ├── injection/ Dynamic context injection + history normalization
62
+ ├── multi-agent/ LaborMarket subagent registry + TaskExecutor
63
+ ├── extensions/ Event-driven plugin system
64
+ ├── skills/ Markdown skill discovery + template rendering
65
+ ├── wire/ Typed async event channel with replay buffer
66
+ ├── background/ In-process async task manager
67
+ └── utils/ ID generation + JSONL helpers
68
+ ```
69
+
70
+ ## Modules
71
+
72
+ ### Core — Agent Loop
73
+
74
+ Nested dual-loop execution engine:
75
+
76
+ - Inner loop: LLM call → tool execution → steering messages → repeat until no more tool calls
77
+ - Outer loop: follow-up messages → re-enter inner loop
78
+
79
+ Each step integrates: checkpoint → compaction check → dynamic injection → history normalization → extension context hook → LLM stream → tool execution → D-Mail check → steering.
80
+
81
+ ```typescript
82
+ const agent = createAgent({
83
+ model: { provider: "anthropic", model: "claude-sonnet-4-20250514", maxContextTokens: 200000 },
84
+ systemPrompt: "You are a helpful assistant.",
85
+ tools: [...],
86
+ maxStepsPerTurn: 50, // Max inner loop iterations (default: 50)
87
+ toolExecution: "parallel", // "sequential" | "parallel" (default: "parallel")
88
+ });
89
+
90
+ // Run a prompt
91
+ const messages = await agent.prompt("Hello");
92
+
93
+ // Continue without new input
94
+ const more = await agent.continue();
95
+
96
+ // Inject messages mid-run
97
+ agent.steer({ role: "user", content: "Focus on X" }); // Injected after current tool execution
98
+ agent.followUp({ role: "user", content: "Also do Y" }); // Injected after inner loop completes
99
+
100
+ // Abort
101
+ agent.abort();
102
+
103
+ // Cleanup
104
+ await agent.dispose();
105
+ ```
106
+
107
+ ### LLM Provider
108
+
109
+ Provider-agnostic abstraction. Built-in Anthropic provider with streaming, retry (3 attempts, exponential backoff), and extended thinking support.
110
+
111
+ ```typescript
112
+ import { registerProvider, resolveProvider } from "@klaus-ai/agent";
113
+
114
+ // Register a custom provider
115
+ registerProvider("openai", (config) => new MyOpenAIProvider(config.apiKey));
116
+
117
+ // Use it
118
+ const agent = createAgent({
119
+ model: { provider: "openai", model: "gpt-4", maxContextTokens: 128000 },
120
+ ...
121
+ });
122
+ ```
123
+
124
+ Provider interface:
125
+
126
+ ```typescript
127
+ interface LLMProvider {
128
+ stream(options: LLMRequestOptions): AsyncIterable<AssistantMessageEvent>;
129
+ }
130
+
131
+ // Stream events: text | tool_call_start | tool_call_delta | thinking | done | error
132
+ ```
133
+
134
+ ### Canonical Message Format
135
+
136
+ Provider-agnostic message types used throughout the framework:
137
+
138
+ ```typescript
139
+ type Message = UserMessage | AssistantMessage | ToolResultMessage;
140
+
141
+ interface UserMessage {
142
+ role: "user";
143
+ content: string | ContentBlock[]; // ContentBlock = TextContent | ImageContent
144
+ }
145
+
146
+ interface AssistantMessage {
147
+ role: "assistant";
148
+ content: AssistantContentBlock[]; // TextBlock | ToolCallBlock | ThinkingBlock
149
+ }
150
+
151
+ interface ToolResultMessage {
152
+ role: "tool_result";
153
+ toolCallId: string;
154
+ content: string | ContentBlock[];
155
+ isError?: boolean;
156
+ }
157
+ ```
158
+
159
+ Extensible via `CustomAgentMessages` interface for framework consumers to add custom message types.
160
+
161
+ ### Tools
162
+
163
+ Tools use TypeBox schemas for parameter validation. The executor supports sequential and parallel modes with approval gating.
164
+
165
+ ```typescript
166
+ import { Type } from "@sinclair/typebox";
167
+ import type { AgentTool } from "@klaus-ai/agent";
168
+
169
+ const readFile: AgentTool = {
170
+ name: "read_file",
171
+ label: "Read File",
172
+ description: "Read a file from disk",
173
+ parameters: Type.Object({
174
+ path: Type.String({ description: "File path" }),
175
+ }),
176
+ approvalAction: "file:read", // Triggers approval unless yolo mode
177
+
178
+ async execute(toolCallId, params, context) {
179
+ // context.signal — AbortSignal
180
+ // context.onUpdate — stream partial results
181
+ // context.approval — approval interface
182
+ // context.agentName — parent agent name
183
+ const text = await fs.readFile(params.path, "utf-8");
184
+ return { content: [{ type: "text", text }] };
185
+ },
186
+ };
187
+ ```
188
+
189
+ Parallel mode: approval and beforeToolCall hooks run sequentially (preflight), then all approved tools execute concurrently.
190
+
191
+ ### Approval
192
+
193
+ Queue-based approval system with three modes:
194
+
195
+ ```typescript
196
+ const agent = createAgent({
197
+ approval: {
198
+ yolo: true, // Auto-approve everything
199
+ autoApproveActions: ["file:read"], // Auto-approve specific actions
200
+ },
201
+ ...
202
+ });
203
+
204
+ // UI integration — pull pending requests and resolve them
205
+ const request = await agent.approval.fetchRequest();
206
+ // request: { id, toolCallId, sender, action, description }
207
+ agent.approval.resolve(request.id, "approve"); // One-time approve
208
+ agent.approval.resolve(request.id, "approve_for_session"); // Auto-approve this action going forward
209
+ agent.approval.resolve(request.id, "reject");
210
+
211
+ // Subagents share yolo/autoApproveActions state via approval.share()
212
+ ```
213
+
214
+ ### Thinking
215
+
216
+ Six-level extended thinking budget:
217
+
218
+ ```typescript
219
+ const agent = createAgent({
220
+ thinkingLevel: "medium", // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"
221
+ model: {
222
+ provider: "anthropic",
223
+ model: "claude-sonnet-4-20250514",
224
+ maxContextTokens: 200000,
225
+ capabilities: { thinking: true },
226
+ },
227
+ ...
228
+ });
229
+
230
+ // Change at runtime
231
+ agent.setThinkingLevel("high");
232
+ ```
233
+
234
+ Token budgets: minimal=1024, low=4096, medium=10240, high=20480, xhigh=40960.
235
+
236
+ ### Session Persistence
237
+
238
+ JSONL tree-based session storage with branching and restore.
239
+
240
+ ```typescript
241
+ const agent = createAgent({
242
+ session: {
243
+ persist: true,
244
+ directory: "./sessions",
245
+ sessionId: "my-session", // Optional, auto-generated if omitted
246
+ },
247
+ ...
248
+ });
249
+
250
+ // Access session tree
251
+ const tree = agent.session.getTree();
252
+ const branch = agent.session.getBranch();
253
+
254
+ // Branch from a specific entry
255
+ agent.session.branch(entryId);
256
+
257
+ // Entry types: message | compaction | branch_summary | model_change |
258
+ // thinking_level_change | checkpoint | custom
259
+ ```
260
+
261
+ Session file format: first line is a header `{ type: "session", version: 1, id, timestamp }`, followed by one JSON entry per line, each with `{ type, id, parentId, timestamp, ... }`.
262
+
263
+ ### Compaction
264
+
265
+ Automatic context compression when token count exceeds threshold.
266
+
267
+ ```typescript
268
+ const agent = createAgent({
269
+ compaction: {
270
+ enabled: true,
271
+ maxContextTokens: 200000, // Defaults to model.maxContextTokens
272
+ reserveTokens: 16384, // Reserve for output
273
+ keepRecentTokens: 20000, // Keep recent messages
274
+ customSummarizer: mySummarizer, // Optional custom summarizer
275
+ },
276
+ ...
277
+ });
278
+ ```
279
+
280
+ Flow: estimate tokens → check threshold → find cut point (respects tool_result boundaries) → summarize discarded messages via LLM → replace with `<compaction-summary>` → persist to session.
281
+
282
+ Built-in `LLMSummarizer` uses the same provider to generate summaries. Supports incremental summarization with `previousSummary`.
283
+
284
+ ### Checkpoint + D-Mail
285
+
286
+ Time-travel via the Steins;Gate-inspired D-Mail mechanism. Checkpoints are created before each agent loop step.
287
+
288
+ ```typescript
289
+ const agent = createAgent({
290
+ session: { persist: true, directory: "./sessions" },
291
+ checkpoint: { enabled: true, enableDMail: true },
292
+ ...
293
+ });
294
+
295
+ // Send a D-Mail — branches session tree back to target checkpoint
296
+ agent.checkpoints.denwaRenji.sendDMail("Try a different approach", checkpointId);
297
+
298
+ // The agent loop automatically:
299
+ // 1. Detects pending D-Mail after tool execution
300
+ // 2. Branches session tree to target checkpoint
301
+ // 3. Injects D-Mail content as <dmail> message
302
+ // 4. Continues execution from that point
303
+ ```
304
+
305
+ ### Dynamic Injection
306
+
307
+ Inject context into the message stream before each LLM call, without modifying the persistent history.
308
+
309
+ ```typescript
310
+ const agent = createAgent({
311
+ injection: [
312
+ {
313
+ async getInjections(history) {
314
+ return [
315
+ { type: "memory", content: "User prefers TypeScript" },
316
+ { type: "context", content: `Current time: ${new Date().toISOString()}` },
317
+ ];
318
+ },
319
+ },
320
+ ],
321
+ ...
322
+ });
323
+ ```
324
+
325
+ Injections are wrapped as `<system-reminder type="...">` user messages. History normalization merges adjacent user messages to maintain valid message alternation.
326
+
327
+ ### Multi-Agent
328
+
329
+ LaborMarket registry with fixed and dynamic subagents. The LLM delegates via the built-in `delegate_task` tool.
330
+
331
+ ```typescript
332
+ const agent = createAgent({
333
+ subagents: {
334
+ researcher: {
335
+ name: "researcher",
336
+ systemPrompt: "You are a research assistant.",
337
+ description: "Handles research tasks",
338
+ tools: [searchTool],
339
+ },
340
+ writer: {
341
+ name: "writer",
342
+ systemPrompt: "You are a writing assistant.",
343
+ description: "Handles writing tasks",
344
+ },
345
+ },
346
+ ...
347
+ });
348
+
349
+ // Dynamic subagent registration at runtime
350
+ agent.laborMarket.addDynamic("analyst", analystAgent, "Data analysis");
351
+ agent.laborMarket.removeDynamic("analyst");
352
+ ```
353
+
354
+ Subagents share the parent's approval state (yolo, autoApproveActions) but have independent approval queues. Subagent events are forwarded to the parent's event stream.
355
+
356
+ ### Extensions
357
+
358
+ Event-driven plugin system with 18 event types across agent lifecycle, tool execution, LLM requests, context, compaction, session, and background tasks.
359
+
360
+ ```typescript
361
+ import type { ExtensionFactory } from "@klaus-ai/agent";
362
+
363
+ const myExtension: ExtensionFactory = (api) => {
364
+ // Register event handlers
365
+ api.on("before_agent_start", (event) => {
366
+ return { systemPrompt: event.systemPrompt + "\nExtra instructions." };
367
+ });
368
+
369
+ api.on("tool_call", (event) => {
370
+ if (event.toolName === "dangerous_tool") {
371
+ return { block: true, reason: "Not allowed" };
372
+ }
373
+ });
374
+
375
+ api.on("before_provider_request", (event) => {
376
+ return { messages: event.messages }; // Modify LLM request
377
+ });
378
+
379
+ api.on("context", (event) => {
380
+ return { messages: [...event.messages, extraMsg] };
381
+ });
382
+
383
+ api.on("before_compact", (event) => {
384
+ return { skip: true }; // Or provide custom summary
385
+ });
386
+
387
+ // Register tools
388
+ api.registerTool(myTool);
389
+
390
+ // Register commands
391
+ api.registerCommand("my-command", async (args) => { ... });
392
+
393
+ // Inject messages into the conversation
394
+ api.sendMessage({ role: "user", content: "Injected by extension" });
395
+ };
396
+
397
+ const agent = createAgent({ extensions: [myExtension], ... });
398
+ ```
399
+
400
+ Interceptable events (return values modify behavior): `before_agent_start`, `before_provider_request`, `tool_call`, `tool_result`, `context`, `before_compact`.
401
+
402
+ Notification events (fire-and-forget): `agent_start`, `agent_end`, `turn_start`, `turn_end`, `message_start`, `message_end`, `after_compact`, `session_start`, `session_switch`, `session_fork`, `task_started`, `task_completed`, `task_failed`.
403
+
404
+ ### Skills
405
+
406
+ Markdown-based skill discovery with frontmatter parsing and template rendering.
407
+
408
+ ```typescript
409
+ const agent = createAgent({
410
+ skills: [{ directory: "./skills", pattern: ".md" }],
411
+ ...
412
+ });
413
+ ```
414
+
415
+ Skill file format (`./skills/review.md`):
416
+
417
+ ```markdown
418
+ ---
419
+ name: review
420
+ description: Code review checklist
421
+ ---
422
+
423
+ Review the code for:
424
+ - Security: {{focus_area}}
425
+ - Performance issues
426
+ - Code style
427
+ ```
428
+
429
+ The LLM invokes skills via the built-in `invoke_skill` tool with optional template variables.
430
+
431
+ ### MCP (Model Context Protocol)
432
+
433
+ Connect to MCP servers and expose their tools to the agent.
434
+
435
+ ```typescript
436
+ const agent = createAgent({
437
+ mcp: {
438
+ servers: [
439
+ {
440
+ name: "filesystem",
441
+ transport: { type: "stdio", command: "mcp-server-fs", args: ["--root", "/tmp"] },
442
+ timeout: 30000,
443
+ },
444
+ {
445
+ name: "web",
446
+ transport: { type: "sse", url: "http://localhost:3001/sse" },
447
+ },
448
+ ],
449
+ clientFactory: (config) => new MyMCPClient(config),
450
+ },
451
+ ...
452
+ });
453
+
454
+ // Check server statuses
455
+ const statuses = agent.mcpAdapter.getStatuses();
456
+ // [{ name: "filesystem", status: "connected", tools: [...] }]
457
+ ```
458
+
459
+ MCP tools are namespaced as `{serverName}__{toolName}` and require approval via `mcp:{serverName}:{toolName}` action.
460
+
461
+ ### Wire (Event Channel)
462
+
463
+ Typed async pub/sub event channel with optional replay buffer. All agent events are automatically published to the wire.
464
+
465
+ ```typescript
466
+ const agent = createAgent({
467
+ wire: { bufferSize: 100 }, // Buffer last 100 messages for late subscribers
468
+ ...
469
+ });
470
+
471
+ // Subscribe to specific event types
472
+ agent.wire.on("tool_execution_end", (msg) => {
473
+ console.log(`Tool ${msg.payload.toolName} completed`);
474
+ });
475
+
476
+ // Subscribe to all events
477
+ agent.wire.subscribe((msg) => {
478
+ console.log(msg.type, msg.payload);
479
+ }, { replay: true }); // Replay buffered messages
480
+
481
+ // Publish custom events
482
+ agent.wire.publish("custom_event", { data: "hello" });
483
+ ```
484
+
485
+ ### Background Tasks
486
+
487
+ In-process async task execution with lifecycle events. The LLM manages tasks via built-in tools.
488
+
489
+ ```typescript
490
+ const agent = createAgent({
491
+ backgroundTasks: {
492
+ factories: {
493
+ build: async (args, signal) => {
494
+ // Long-running task with abort support
495
+ return { success: true };
496
+ },
497
+ },
498
+ },
499
+ ...
500
+ });
501
+
502
+ // Programmatic access
503
+ const handle = agent.backgroundTasks.spawn("my-task", async (signal) => {
504
+ return await doWork(signal);
505
+ });
506
+
507
+ console.log(handle.status); // "running" | "completed" | "failed"
508
+ handle.abort();
509
+ ```
510
+
511
+ Built-in tools: `start_background_task`, `check_task_status`, `get_task_result`.
512
+
513
+ ### Hooks
514
+
515
+ User-level hooks for transforming context and intercepting tool calls:
516
+
517
+ ```typescript
518
+ const agent = createAgent({
519
+ hooks: {
520
+ // Transform messages before sending to LLM
521
+ transformContext: async (messages) => {
522
+ return messages.filter(m => ...);
523
+ },
524
+ // Custom message format conversion
525
+ convertToLlm: (messages) => {
526
+ return messages.filter(m => m.role === "user" || m.role === "assistant" || m.role === "tool_result");
527
+ },
528
+ // Before/after tool execution
529
+ beforeToolCall: async (ctx) => {
530
+ // return { block: true, reason: "..." } to block
531
+ },
532
+ afterToolCall: async (ctx) => {
533
+ // return { content, details, isError } to modify result
534
+ },
535
+ },
536
+ ...
537
+ });
538
+ ```
539
+
540
+ ## Events
541
+
542
+ Subscribe to the agent event stream for real-time updates:
543
+
544
+ ```typescript
545
+ agent.subscribe((event) => {
546
+ switch (event.type) {
547
+ case "agent_start":
548
+ case "agent_end": // { messages }
549
+ case "turn_start":
550
+ case "turn_end": // { message, toolResults }
551
+ case "message_start": // { message }
552
+ case "message_update": // { message, event: text|tool_call_start|tool_call_delta|thinking|done }
553
+ case "message_end": // { message, usage }
554
+ case "tool_execution_start": // { toolCallId, toolName, args }
555
+ case "tool_execution_update": // { toolCallId, toolName, partialResult }
556
+ case "tool_execution_end": // { toolCallId, toolName, result, isError }
557
+ case "approval_request": // { request }
558
+ case "approval_response": // { requestId, response }
559
+ case "compaction_start":
560
+ case "compaction_end": // { summary }
561
+ case "checkpoint": // { id }
562
+ case "dmail_received": // { checkpoint, content }
563
+ case "task_started": // { taskId, taskName }
564
+ case "task_completed": // { taskId, taskName }
565
+ case "task_failed": // { taskId, taskName, error }
566
+ case "error": // { error }
567
+ }
568
+ });
569
+ ```
570
+
571
+ ## Full Example
572
+
573
+ ```typescript
574
+ import { createAgent } from "@klaus-ai/agent";
575
+ import { Type } from "@sinclair/typebox";
576
+
577
+ const agent = createAgent({
578
+ model: {
579
+ provider: "anthropic",
580
+ model: "claude-sonnet-4-20250514",
581
+ maxContextTokens: 200000,
582
+ capabilities: { vision: true, thinking: true },
583
+ },
584
+ systemPrompt: "You are a coding assistant.",
585
+ tools: [readFileTool, writeFileTool, searchTool],
586
+ thinkingLevel: "medium",
587
+ toolExecution: "parallel",
588
+ maxStepsPerTurn: 30,
589
+
590
+ approval: { autoApproveActions: ["file:read", "search"] },
591
+
592
+ session: { persist: true, directory: "./sessions" },
593
+ compaction: { enabled: true, reserveTokens: 16384, keepRecentTokens: 20000 },
594
+ checkpoint: { enabled: true, enableDMail: true },
595
+
596
+ injection: [memoryProvider, contextProvider],
597
+ extensions: [loggingExtension, guardExtension],
598
+
599
+ subagents: {
600
+ researcher: {
601
+ name: "researcher",
602
+ systemPrompt: "You research topics thoroughly.",
603
+ description: "Research assistant",
604
+ tools: [searchTool],
605
+ },
606
+ },
607
+
608
+ skills: [{ directory: "./skills" }],
609
+
610
+ mcp: {
611
+ servers: [{ name: "fs", transport: { type: "stdio", command: "mcp-fs" } }],
612
+ clientFactory: (config) => new MCPClient(config),
613
+ },
614
+
615
+ wire: { bufferSize: 100 },
616
+ backgroundTasks: { factories: { build: buildTaskFactory } },
617
+
618
+ hooks: {
619
+ transformContext: async (msgs) => msgs,
620
+ beforeToolCall: async (ctx) => {},
621
+ afterToolCall: async (ctx) => {},
622
+ },
623
+ });
624
+
625
+ agent.subscribe((event) => {
626
+ if (event.type === "message_update" && event.event.type === "text") {
627
+ process.stdout.write(event.event.text);
628
+ }
629
+ });
630
+
631
+ await agent.prompt("Help me refactor the auth module");
632
+ await agent.dispose();
633
+ ```
634
+
635
+ ## API Reference
636
+
637
+ ### `createAgent(config): Agent`
638
+
639
+ | Config | Type | Required | Default | Description |
640
+ |--------|------|----------|---------|-------------|
641
+ | `model` | `ModelConfig` | yes | — | Provider, model ID, maxContextTokens, capabilities |
642
+ | `systemPrompt` | `string \| () => string` | yes | — | Static or dynamic system prompt |
643
+ | `tools` | `AgentTool[]` | yes | — | Tool definitions with TypeBox schemas |
644
+ | `approval` | `ApprovalConfig` | no | `{}` | yolo, autoApproveActions |
645
+ | `thinkingLevel` | `ThinkingLevel` | no | `"off"` | Extended thinking budget |
646
+ | `toolExecution` | `"sequential" \| "parallel"` | no | `"parallel"` | Tool execution mode |
647
+ | `maxStepsPerTurn` | `number` | no | `50` | Max inner loop iterations |
648
+ | `hooks` | `AgentHooks` | no | — | transformContext, convertToLlm, beforeToolCall, afterToolCall |
649
+ | `session` | `SessionConfig` | no | — | persist, directory, sessionId |
650
+ | `compaction` | `CompactionConfig` | no | — | enabled, reserveTokens, keepRecentTokens, customSummarizer |
651
+ | `checkpoint` | `CheckpointConfig` | no | — | enabled, enableDMail |
652
+ | `injection` | `DynamicInjectionProvider[]` | no | — | Dynamic context providers |
653
+ | `extensions` | `ExtensionFactory[]` | no | — | Plugin factories |
654
+ | `subagents` | `Record<string, SubagentConfig>` | no | — | Named subagent configs |
655
+ | `skills` | `SkillSource[]` | no | — | Skill directories |
656
+ | `mcp` | `{ servers, clientFactory }` | no | — | MCP server configs |
657
+ | `wire` | `{ bufferSize }` | no | `{ bufferSize: 0 }` | Event channel config |
658
+ | `backgroundTasks` | `{ factories }` | no | — | Background task factories |
659
+ | `provider` | `LLMProvider` | no | — | Custom LLM provider (bypasses registry) |
660
+
661
+ ### `Agent` Instance
662
+
663
+ | Method / Property | Description |
664
+ |-------------------|-------------|
665
+ | `prompt(input)` | Send input and run the agent loop. Returns all messages. |
666
+ | `continue()` | Re-enter the loop without new input. |
667
+ | `steer(message)` | Inject a message after current tool execution. |
668
+ | `followUp(message)` | Inject a message after inner loop completes. |
669
+ | `abort()` | Abort the current run. |
670
+ | `subscribe(fn)` | Subscribe to events. Returns unsubscribe function. |
671
+ | `dispose()` | Cleanup all resources. |
672
+ | `state` | Current `AgentState` (systemPrompt, model, tools, messages, isRunning). |
673
+ | `approval` | `Approval` instance. |
674
+ | `session` | `SessionManager` (if configured). |
675
+ | `checkpoints` | `CheckpointManager` (if configured). |
676
+ | `extensions` | `ExtensionRunner` (if configured). |
677
+ | `injections` | `InjectionManager` (if configured). |
678
+ | `laborMarket` | `LaborMarket` (if subagents configured). |
679
+ | `mcpAdapter` | `MCPAdapter` (if MCP configured). |
680
+ | `wire` | `Wire` event channel (always available). |
681
+ | `backgroundTasks` | `BackgroundTaskManager` (if configured). |
682
+ | `setSystemPrompt(prompt)` | Update system prompt. |
683
+ | `setModel(model)` | Update model config. |
684
+ | `setTools(tools)` | Replace tools (not while running). |
685
+ | `setThinkingLevel(level)` | Update thinking level (not while running). |
@@ -0,0 +1,18 @@
1
+ import type { Approval, ApprovalConfig, ApprovalRequest, ApprovalResponse } from "./types.js";
2
+ export declare class ApprovalImpl implements Approval {
3
+ private _yolo;
4
+ private _autoApproveActions;
5
+ private _pending;
6
+ private _queue;
7
+ private _waiters;
8
+ constructor(config?: ApprovalConfig);
9
+ request(sender: string, action: string, description: string, toolCallId: string): Promise<boolean>;
10
+ fetchRequest(): Promise<ApprovalRequest>;
11
+ /** Cancel all pending waiters (e.g., on agent dispose) */
12
+ cancelPendingWaiters(): void;
13
+ resolve(requestId: string, response: ApprovalResponse): void;
14
+ setYolo(yolo: boolean): void;
15
+ isYolo(): boolean;
16
+ get autoApproveActions(): Set<string>;
17
+ share(): Approval;
18
+ }