@jackchen_me/open-multi-agent 0.2.0 → 1.0.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 (104) hide show
  1. package/.github/workflows/ci.yml +1 -1
  2. package/CLAUDE.md +11 -3
  3. package/README.md +87 -20
  4. package/README_zh.md +85 -25
  5. package/dist/agent/agent.d.ts +15 -1
  6. package/dist/agent/agent.d.ts.map +1 -1
  7. package/dist/agent/agent.js +144 -10
  8. package/dist/agent/agent.js.map +1 -1
  9. package/dist/agent/loop-detector.d.ts +39 -0
  10. package/dist/agent/loop-detector.d.ts.map +1 -0
  11. package/dist/agent/loop-detector.js +122 -0
  12. package/dist/agent/loop-detector.js.map +1 -0
  13. package/dist/agent/pool.d.ts +2 -1
  14. package/dist/agent/pool.d.ts.map +1 -1
  15. package/dist/agent/pool.js +4 -2
  16. package/dist/agent/pool.js.map +1 -1
  17. package/dist/agent/runner.d.ts +23 -1
  18. package/dist/agent/runner.d.ts.map +1 -1
  19. package/dist/agent/runner.js +113 -12
  20. package/dist/agent/runner.js.map +1 -1
  21. package/dist/index.d.ts +3 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/llm/adapter.d.ts +4 -1
  26. package/dist/llm/adapter.d.ts.map +1 -1
  27. package/dist/llm/adapter.js +11 -0
  28. package/dist/llm/adapter.js.map +1 -1
  29. package/dist/llm/copilot.d.ts.map +1 -1
  30. package/dist/llm/copilot.js +2 -1
  31. package/dist/llm/copilot.js.map +1 -1
  32. package/dist/llm/gemini.d.ts +65 -0
  33. package/dist/llm/gemini.d.ts.map +1 -0
  34. package/dist/llm/gemini.js +317 -0
  35. package/dist/llm/gemini.js.map +1 -0
  36. package/dist/llm/grok.d.ts +21 -0
  37. package/dist/llm/grok.d.ts.map +1 -0
  38. package/dist/llm/grok.js +24 -0
  39. package/dist/llm/grok.js.map +1 -0
  40. package/dist/llm/openai-common.d.ts +8 -1
  41. package/dist/llm/openai-common.d.ts.map +1 -1
  42. package/dist/llm/openai-common.js +35 -2
  43. package/dist/llm/openai-common.js.map +1 -1
  44. package/dist/llm/openai.d.ts +1 -1
  45. package/dist/llm/openai.d.ts.map +1 -1
  46. package/dist/llm/openai.js +20 -2
  47. package/dist/llm/openai.js.map +1 -1
  48. package/dist/orchestrator/orchestrator.d.ts.map +1 -1
  49. package/dist/orchestrator/orchestrator.js +89 -9
  50. package/dist/orchestrator/orchestrator.js.map +1 -1
  51. package/dist/task/queue.d.ts +31 -2
  52. package/dist/task/queue.d.ts.map +1 -1
  53. package/dist/task/queue.js +69 -2
  54. package/dist/task/queue.js.map +1 -1
  55. package/dist/tool/text-tool-extractor.d.ts +32 -0
  56. package/dist/tool/text-tool-extractor.d.ts.map +1 -0
  57. package/dist/tool/text-tool-extractor.js +187 -0
  58. package/dist/tool/text-tool-extractor.js.map +1 -0
  59. package/dist/types.d.ts +139 -7
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/utils/trace.d.ts +12 -0
  62. package/dist/utils/trace.d.ts.map +1 -0
  63. package/dist/utils/trace.js +30 -0
  64. package/dist/utils/trace.js.map +1 -0
  65. package/examples/06-local-model.ts +1 -0
  66. package/examples/08-gemma4-local.ts +76 -87
  67. package/examples/09-structured-output.ts +73 -0
  68. package/examples/10-task-retry.ts +132 -0
  69. package/examples/11-trace-observability.ts +133 -0
  70. package/examples/12-grok.ts +154 -0
  71. package/examples/13-gemini.ts +48 -0
  72. package/package.json +11 -1
  73. package/src/agent/agent.ts +159 -10
  74. package/src/agent/loop-detector.ts +137 -0
  75. package/src/agent/pool.ts +9 -2
  76. package/src/agent/runner.ts +148 -19
  77. package/src/index.ts +15 -0
  78. package/src/llm/adapter.ts +12 -1
  79. package/src/llm/copilot.ts +2 -1
  80. package/src/llm/gemini.ts +378 -0
  81. package/src/llm/grok.ts +29 -0
  82. package/src/llm/openai-common.ts +41 -2
  83. package/src/llm/openai.ts +23 -3
  84. package/src/orchestrator/orchestrator.ts +105 -11
  85. package/src/task/queue.ts +73 -3
  86. package/src/tool/text-tool-extractor.ts +219 -0
  87. package/src/types.ts +157 -6
  88. package/src/utils/trace.ts +34 -0
  89. package/tests/agent-hooks.test.ts +473 -0
  90. package/tests/agent-pool.test.ts +212 -0
  91. package/tests/approval.test.ts +464 -0
  92. package/tests/built-in-tools.test.ts +393 -0
  93. package/tests/gemini-adapter.test.ts +97 -0
  94. package/tests/grok-adapter.test.ts +74 -0
  95. package/tests/llm-adapters.test.ts +357 -0
  96. package/tests/loop-detection.test.ts +456 -0
  97. package/tests/openai-fallback.test.ts +159 -0
  98. package/tests/orchestrator.test.ts +281 -0
  99. package/tests/scheduler.test.ts +221 -0
  100. package/tests/team-messaging.test.ts +329 -0
  101. package/tests/text-tool-extractor.test.ts +170 -0
  102. package/tests/trace.test.ts +453 -0
  103. package/vitest.config.ts +9 -0
  104. package/examples/09-gemma4-auto-orchestration.ts +0 -162
@@ -18,6 +18,6 @@ jobs:
18
18
  with:
19
19
  node-version: ${{ matrix.node-version }}
20
20
  cache: npm
21
- - run: npm ci
21
+ - run: rm -f package-lock.json && npm install
22
22
  - run: npm run lint
23
23
  - run: npm test
package/CLAUDE.md CHANGED
@@ -12,7 +12,7 @@ npm test # Run all tests (vitest run)
12
12
  npm run test:watch # Vitest watch mode
13
13
  ```
14
14
 
15
- No test files exist yet in `tests/`. Examples in `examples/` are standalone scripts requiring API keys (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`).
15
+ Tests live in `tests/` (vitest). Examples in `examples/` are standalone scripts requiring API keys (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`).
16
16
 
17
17
  ## Architecture
18
18
 
@@ -41,7 +41,7 @@ This is the framework's key feature. When `runTeam()` is called:
41
41
  |-------|-------|----------------|
42
42
  | Orchestrator | `orchestrator/orchestrator.ts`, `orchestrator/scheduler.ts` | Top-level API, task decomposition, coordinator pattern |
43
43
  | Team | `team/team.ts`, `team/messaging.ts` | Agent roster, MessageBus (point-to-point + broadcast), SharedMemory binding |
44
- | Agent | `agent/agent.ts`, `agent/runner.ts`, `agent/pool.ts` | Agent lifecycle (idle→running→completed/error), conversation loop, concurrency pool with Semaphore |
44
+ | Agent | `agent/agent.ts`, `agent/runner.ts`, `agent/pool.ts`, `agent/structured-output.ts` | Agent lifecycle (idle→running→completed/error), conversation loop, concurrency pool with Semaphore, structured output validation |
45
45
  | Task | `task/queue.ts`, `task/task.ts` | Dependency-aware queue, auto-unblock on completion, cascade failure to dependents |
46
46
  | Tool | `tool/framework.ts`, `tool/executor.ts`, `tool/built-in/` | `defineTool()` with Zod schemas, ToolRegistry, parallel batch execution with concurrency semaphore |
47
47
  | LLM | `llm/adapter.ts`, `llm/anthropic.ts`, `llm/openai.ts` | `LLMAdapter` interface (`chat` + `stream`), factory `createAdapter()` |
@@ -57,10 +57,18 @@ This is the framework's key feature. When `runTeam()` is called:
57
57
 
58
58
  Two independent semaphores: `AgentPool` (max concurrent agent runs, default 5) and `ToolExecutor` (max concurrent tool calls, default 4).
59
59
 
60
+ ### Structured Output
61
+
62
+ Optional `outputSchema` (Zod) on `AgentConfig`. When set, the agent's final output is parsed as JSON and validated. On validation failure, one retry with error feedback is attempted. Validated data is available via `result.structured`. Logic lives in `agent/structured-output.ts`, wired into `Agent.executeRun()`.
63
+
64
+ ### Task Retry
65
+
66
+ Optional `maxRetries`, `retryDelayMs`, `retryBackoff` on task config (used via `runTasks()`). `executeWithRetry()` in `orchestrator.ts` handles the retry loop with exponential backoff (capped at 30s). Token usage is accumulated across all attempts. Emits `task_retry` event via `onProgress`.
67
+
60
68
  ### Error Handling
61
69
 
62
70
  - Tool errors → caught, returned as `ToolResult(isError: true)`, never thrown
63
- - Task failures → cascade to all dependents; independent tasks continue
71
+ - Task failures → retry if `maxRetries > 0`, then cascade to all dependents; independent tasks continue
64
72
  - LLM API errors → propagate to caller
65
73
 
66
74
  ### Built-in Tools
package/README.md CHANGED
@@ -1,24 +1,29 @@
1
1
  # Open Multi-Agent
2
2
 
3
- Build AI agent teams that decompose goals into tasks automatically. Define agents with roles and tools, describe a goal — the framework plans the task graph, schedules dependencies, and runs everything in parallel.
3
+ TypeScript framework for multi-agent orchestration. One `runTeam()` call from goal to result — the framework decomposes it into tasks, resolves dependencies, and runs agents in parallel.
4
4
 
5
- 3 runtime dependencies. 27 source files. One `runTeam()` call from goal to result.
5
+ 3 runtime dependencies · 33 source files · Deploys anywhere Node.js runs · Mentioned in [Latent Space](https://www.latent.space/p/ainews-a-quiet-april-fools) AI News
6
6
 
7
7
  [![GitHub stars](https://img.shields.io/github/stars/JackChen-me/open-multi-agent)](https://github.com/JackChen-me/open-multi-agent/stargazers)
8
8
  [![license](https://img.shields.io/github/license/JackChen-me/open-multi-agent)](./LICENSE)
9
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue)](https://www.typescriptlang.org/)
10
+ [![coverage](https://img.shields.io/badge/coverage-71%25-brightgreen)](https://github.com/JackChen-me/open-multi-agent/actions)
10
11
 
11
12
  **English** | [中文](./README_zh.md)
12
13
 
13
14
  ## Why Open Multi-Agent?
14
15
 
15
- - **Auto Task Decomposition** — Describe a goal in plain text. A built-in coordinator agent breaks it into a task DAG with dependencies and assignees no manual orchestration needed.
16
- - **Multi-Agent Teams** — Define agents with different roles, tools, and even different models. They collaborate through a message bus and shared memory.
17
- - **Task DAG Scheduling** — Tasks have dependencies. The framework resolves them topologically dependent tasks wait, independent tasks run in parallel.
18
- - **Model Agnostic** — Claude, GPT, Gemma 4, and local models (Ollama, vLLM, LM Studio) in the same team. Swap models per agent via `baseURL`.
16
+ - **Goal In, Result Out** — `runTeam(team, "Build a REST API")`. A coordinator agent auto-decomposes the goal into a task DAG with dependencies and assignees, runs independent tasks in parallel, and synthesizes the final output. No manual task definitions or graph wiring required.
17
+ - **TypeScript-Native** — Built for the Node.js ecosystem. `npm install`, import, run. No Python runtime, no subprocess bridge, no sidecar services. Embed in Express, Next.js, serverless functions, or CI/CD pipelines.
18
+ - **Auditable and Lightweight** — 3 runtime dependencies (`@anthropic-ai/sdk`, `openai`, `zod`). 33 source files. The entire codebase is readable in an afternoon.
19
+ - **Model Agnostic** — Claude, GPT, Gemma 4, and local models (Ollama, vLLM, LM Studio, llama.cpp server) in the same team. Swap models per agent via `baseURL`.
20
+ - **Multi-Agent Collaboration** — Agents with different roles, tools, and models collaborate through a message bus and shared memory.
19
21
  - **Structured Output** — Add `outputSchema` (Zod) to any agent. Output is parsed as JSON, validated, and auto-retried once on failure. Access typed results via `result.structured`.
20
22
  - **Task Retry** — Set `maxRetries` on tasks for automatic retry with exponential backoff. Failed attempts accumulate token usage for accurate billing.
21
- - **In-Process Execution** — No subprocess overhead. Everything runs in one Node.js process. Deploy to serverless, Docker, CI/CD.
23
+ - **Human-in-the-Loop** — Optional `onApproval` callback on `runTasks()`. After each batch of tasks completes, your callback decides whether to proceed or abort remaining work.
24
+ - **Lifecycle Hooks** — `beforeRun` / `afterRun` on `AgentConfig`. Intercept the prompt before execution or post-process results after. Throw from either hook to abort.
25
+ - **Loop Detection** — `loopDetection` on `AgentConfig` catches stuck agents repeating the same tool calls or text output. Configurable action: warn (default), terminate, or custom callback.
26
+ - **Observability** — Optional `onTrace` callback emits structured spans for every LLM call, tool execution, task, and agent run — with timing, token usage, and a shared `runId` for correlation. Zero overhead when not subscribed, zero extra dependencies.
22
27
 
23
28
  ## Quick Start
24
29
 
@@ -28,7 +33,12 @@ Requires Node.js >= 18.
28
33
  npm install @jackchen_me/open-multi-agent
29
34
  ```
30
35
 
31
- Set `ANTHROPIC_API_KEY` (and optionally `OPENAI_API_KEY` or `GITHUB_TOKEN` for Copilot) in your environment. Local models via Ollama require no API key — see [example 06](examples/06-local-model.ts).
36
+ Set the API key for your provider. Local models via Ollama require no API key — see [example 06](examples/06-local-model.ts).
37
+
38
+ - `ANTHROPIC_API_KEY`
39
+ - `OPENAI_API_KEY`
40
+ - `GEMINI_API_KEY`
41
+ - `GITHUB_TOKEN` (for Copilot)
32
42
 
33
43
  Three agents, one goal — the framework handles the rest:
34
44
 
@@ -100,12 +110,6 @@ Tokens: 12847 output tokens
100
110
  | Auto-orchestrated team | `runTeam()` | Give a goal, framework plans and executes |
101
111
  | Explicit pipeline | `runTasks()` | You define the task graph and assignments |
102
112
 
103
- ## Contributors
104
-
105
- <a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
106
- <img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent" />
107
- </a>
108
-
109
113
  ## Examples
110
114
 
111
115
  All examples are runnable scripts in [`examples/`](./examples/). Run any of them with `npx tsx`:
@@ -123,8 +127,12 @@ npx tsx examples/01-single-agent.ts
123
127
  | [05 — Copilot](examples/05-copilot-test.ts) | GitHub Copilot as an LLM provider |
124
128
  | [06 — Local Model](examples/06-local-model.ts) | Ollama + Claude in one pipeline via `baseURL` (works with vLLM, LM Studio, etc.) |
125
129
  | [07 — Fan-Out / Aggregate](examples/07-fan-out-aggregate.ts) | `runParallel()` MapReduce — 3 analysts in parallel, then synthesize |
126
- | [08 — Gemma 4 Local](examples/08-gemma4-local.ts) | Pure-local Gemma 4 agent team with tool-calling — zero API cost |
127
- | [09 — Gemma 4 Auto-Orchestration](examples/09-gemma4-auto-orchestration.ts) | `runTeam()` with Gemma 4 as coordinator auto task decomposition, fully local |
130
+ | [08 — Gemma 4 Local](examples/08-gemma4-local.ts) | `runTasks()` + `runTeam()` with local Gemma 4 via Ollama — zero API cost |
131
+ | [09 — Structured Output](examples/09-structured-output.ts) | `outputSchema` (Zod) on AgentConfigvalidated JSON via `result.structured` |
132
+ | [10 — Task Retry](examples/10-task-retry.ts) | `maxRetries` / `retryDelayMs` / `retryBackoff` with `task_retry` progress events |
133
+ | [11 — Trace Observability](examples/11-trace-observability.ts) | `onTrace` callback — structured spans for LLM calls, tools, tasks, and agents |
134
+ | [12 — Grok](examples/12-grok.ts) | Same as example 02 (`runTeam()` collaboration) with Grok (`XAI_API_KEY`) |
135
+ | [13 — Gemini](examples/13-gemini.ts) | Gemini adapter smoke test with `gemini-2.5-flash` (`GEMINI_API_KEY`) |
128
136
 
129
137
  ## Architecture
130
138
 
@@ -158,6 +166,8 @@ npx tsx examples/01-single-agent.ts
158
166
  │ - stream() │ │ - AnthropicAdapter │
159
167
  └────────┬──────────┘ │ - OpenAIAdapter │
160
168
  │ │ - CopilotAdapter │
169
+ │ │ - GeminiAdapter │
170
+ │ │ - GrokAdapter │
161
171
  │ └──────────────────────┘
162
172
  ┌────────▼──────────┐
163
173
  │ AgentRunner │ ┌──────────────────────┐
@@ -183,12 +193,55 @@ npx tsx examples/01-single-agent.ts
183
193
  |----------|--------|---------|--------|
184
194
  | Anthropic (Claude) | `provider: 'anthropic'` | `ANTHROPIC_API_KEY` | Verified |
185
195
  | OpenAI (GPT) | `provider: 'openai'` | `OPENAI_API_KEY` | Verified |
196
+ | Grok (xAI) | `provider: 'grok'` | `XAI_API_KEY` | Verified |
186
197
  | GitHub Copilot | `provider: 'copilot'` | `GITHUB_TOKEN` | Verified |
198
+ | Gemini | `provider: 'gemini'` | `GEMINI_API_KEY` | Verified |
187
199
  | Ollama / vLLM / LM Studio | `provider: 'openai'` + `baseURL` | — | Verified |
200
+ | llama.cpp server | `provider: 'openai'` + `baseURL` | — | Verified |
188
201
 
189
202
  Verified local models with tool-calling: **Gemma 4** (see [example 08](examples/08-gemma4-local.ts)).
190
203
 
191
- Any OpenAI-compatible API should work via `provider: 'openai'` + `baseURL` (DeepSeek, Groq, Mistral, Qwen, MiniMax, etc.). These providers have not been fully verified yet — contributions welcome via [#25](https://github.com/JackChen-me/open-multi-agent/issues/25).
204
+ Any OpenAI-compatible API should work via `provider: 'openai'` + `baseURL` (DeepSeek, Groq, Mistral, Qwen, MiniMax, etc.). **Grok now has first-class support** via `provider: 'grok'`.
205
+
206
+ ### Local Model Tool-Calling
207
+
208
+ The framework supports tool-calling with local models served by Ollama, vLLM, LM Studio, or llama.cpp. Tool-calling is handled natively by these servers via the OpenAI-compatible API.
209
+
210
+ **Verified models:** Gemma 4, Llama 3.1, Qwen 3, Mistral, Phi-4. See the full list at [ollama.com/search?c=tools](https://ollama.com/search?c=tools).
211
+
212
+ **Fallback extraction:** If a local model returns tool calls as text instead of using the `tool_calls` wire format (common with thinking models or misconfigured servers), the framework automatically extracts them from the text output.
213
+
214
+ **Timeout:** Local inference can be slow. Use `timeoutMs` on `AgentConfig` to prevent indefinite hangs:
215
+
216
+ ```typescript
217
+ const localAgent: AgentConfig = {
218
+ name: 'local',
219
+ model: 'llama3.1',
220
+ provider: 'openai',
221
+ baseURL: 'http://localhost:11434/v1',
222
+ apiKey: 'ollama',
223
+ tools: ['bash', 'file_read'],
224
+ timeoutMs: 120_000, // abort after 2 minutes
225
+ }
226
+ ```
227
+
228
+ **Troubleshooting:**
229
+ - Model not calling tools? Ensure it appears in Ollama's [Tools category](https://ollama.com/search?c=tools). Not all models support tool-calling.
230
+ - Using Ollama? Update to the latest version (`ollama update`) — older versions have known tool-calling bugs.
231
+ - Proxy interfering? Use `no_proxy=localhost` when running against local servers.
232
+
233
+ ### LLM Configuration Examples
234
+
235
+ ```typescript
236
+ const grokAgent: AgentConfig = {
237
+ name: 'grok-agent',
238
+ provider: 'grok',
239
+ model: 'grok-4',
240
+ systemPrompt: 'You are a helpful assistant.',
241
+ }
242
+ ```
243
+
244
+ (Set your `XAI_API_KEY` environment variable — no `baseURL` needed anymore.)
192
245
 
193
246
  ## Contributing
194
247
 
@@ -198,16 +251,30 @@ Issues, feature requests, and PRs are welcome. Some areas where contributions wo
198
251
  - **Examples** — Real-world workflows and use cases.
199
252
  - **Documentation** — Guides, tutorials, and API docs.
200
253
 
254
+ ## Author
255
+
256
+ > JackChen — Ex PM (¥100M+ revenue), now indie builder. Follow on [X](https://x.com/JackChen_x) for AI Agent insights.
257
+
258
+ ## Contributors
259
+
260
+ <a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
261
+ <img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent&v=20260405" />
262
+ </a>
263
+
201
264
  ## Star History
202
265
 
203
266
  <a href="https://star-history.com/#JackChen-me/open-multi-agent&Date">
204
267
  <picture>
205
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260403" />
206
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260403" />
207
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260403" />
268
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260405" />
269
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260405" />
270
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260405" />
208
271
  </picture>
209
272
  </a>
210
273
 
274
+ ## Translations
275
+
276
+ Help translate this README — [open a PR](https://github.com/JackChen-me/open-multi-agent/pulls).
277
+
211
278
  ## License
212
279
 
213
280
  MIT
package/README_zh.md CHANGED
@@ -1,24 +1,29 @@
1
1
  # Open Multi-Agent
2
2
 
3
- 构建能自动拆解目标的 AI 智能体团队。定义智能体的角色和工具,描述一个目标——框架自动规划任务图、调度依赖、并行执行。
3
+ TypeScript 多智能体编排框架。一次 `runTeam()` 调用从目标到结果——框架自动拆解任务、解析依赖、并行执行。
4
4
 
5
- 3 个运行时依赖,27 个源文件,一次 `runTeam()` 调用从目标到结果。
5
+ 3 个运行时依赖 · 33 个源文件 · Node.js 能跑的地方都能部署 · 被 [Latent Space](https://www.latent.space/p/ainews-a-quiet-april-fools) AI News 提及(AI 工程领域头部 Newsletter,17 万+订阅者)
6
6
 
7
7
  [![GitHub stars](https://img.shields.io/github/stars/JackChen-me/open-multi-agent)](https://github.com/JackChen-me/open-multi-agent/stargazers)
8
8
  [![license](https://img.shields.io/github/license/JackChen-me/open-multi-agent)](./LICENSE)
9
9
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.6-blue)](https://www.typescriptlang.org/)
10
+ [![coverage](https://img.shields.io/badge/coverage-71%25-brightgreen)](https://github.com/JackChen-me/open-multi-agent/actions)
10
11
 
11
12
  [English](./README.md) | **中文**
12
13
 
13
14
  ## 为什么选择 Open Multi-Agent?
14
15
 
15
- - **自动任务拆解**用自然语言描述目标,内置的协调者智能体自动将其拆解为带依赖关系和分配的任务图——无需手动编排。
16
- - **多智能体团队**定义不同角色、工具甚至不同模型的智能体。它们通过消息总线和共享内存协作。
17
- - **任务 DAG 调度** 任务之间存在依赖关系。框架进行拓扑排序——有依赖的任务等待,无依赖的任务并行执行。
18
- - **模型无关** — Claude、GPT、Gemma 4 和本地模型(Ollama、vLLM、LM Studio)可以在同一个团队中使用。通过 `baseURL` 即可接入任何 OpenAI 兼容服务。
16
+ - **目标进,结果出**`runTeam(team, "构建一个 REST API")`。协调者智能体自动将目标拆解为带依赖关系的任务图,分配给对应智能体,独立任务并行执行,最终合成输出。无需手动定义任务或编排流程图。
17
+ - **TypeScript 原生** 为 Node.js 生态而生。`npm install` 即用,无需 Python 运行时、无子进程桥接、无额外基础设施。可嵌入 Express、Next.js、Serverless 函数或 CI/CD 流水线。
18
+ - **可审计、极轻量** 3 个运行时依赖(`@anthropic-ai/sdk`、`openai`、`zod`),33 个源文件。一个下午就能读完全部源码。
19
+ - **模型无关** — Claude、GPT、Gemma 4 和本地模型(Ollama、vLLM、LM Studio、llama.cpp server)可以在同一个团队中使用。通过 `baseURL` 即可接入任何 OpenAI 兼容服务。
20
+ - **多智能体协作** — 定义不同角色、工具和模型的智能体,通过消息总线和共享内存协作。
19
21
  - **结构化输出** — 为任意智能体添加 `outputSchema`(Zod),输出自动解析为 JSON 并校验,校验失败自动重试一次。通过 `result.structured` 获取类型化结果。
20
22
  - **任务重试** — 为任务设置 `maxRetries`,失败时自动指数退避重试。所有尝试的 token 用量累计,确保计费准确。
21
- - **进程内执行**没有子进程开销。所有内容在一个 Node.js 进程中运行。可部署到 Serverless、Docker、CI/CD。
23
+ - **人机协同**`runTasks()` 支持可选的 `onApproval` 回调。每批任务完成后,由你的回调决定是否继续执行后续任务。
24
+ - **生命周期钩子** — `AgentConfig` 上的 `beforeRun` / `afterRun`。在执行前拦截 prompt,或在执行后处理结果。从钩子中 throw 可中止运行。
25
+ - **循环检测** — `AgentConfig` 上的 `loopDetection` 可检测智能体重复相同工具调用或文本输出的卡死循环。可配置行为:警告(默认)、终止、或自定义回调。
26
+ - **可观测性** — 可选的 `onTrace` 回调为每次 LLM 调用、工具执行、任务和智能体运行发出结构化 span 事件——包含耗时、token 用量和共享的 `runId` 用于关联追踪。未订阅时零开销,零额外依赖。
22
27
 
23
28
  ## 快速开始
24
29
 
@@ -28,7 +33,13 @@
28
33
  npm install @jackchen_me/open-multi-agent
29
34
  ```
30
35
 
31
- 在环境变量中设置 `ANTHROPIC_API_KEY`(以及可选的 `OPENAI_API_KEY` 或用于 Copilot 的 `GITHUB_TOKEN`)。通过 Ollama 使用本地模型无需 API key — 参见 [example 06](examples/06-local-model.ts)。
36
+ 根据使用的 Provider 设置对应的 API key。通过 Ollama 使用本地模型无需 API key — 参见 [example 06](examples/06-local-model.ts)。
37
+
38
+ - `ANTHROPIC_API_KEY`
39
+ - `OPENAI_API_KEY`
40
+ - `GEMINI_API_KEY`
41
+ - `XAI_API_KEY`(Grok)
42
+ - `GITHUB_TOKEN`(Copilot)
32
43
 
33
44
  三个智能体,一个目标——框架处理剩下的一切:
34
45
 
@@ -92,10 +103,6 @@ Success: true
92
103
  Tokens: 12847 output tokens
93
104
  ```
94
105
 
95
- ## 作者
96
-
97
- > JackChen — 前 WPS 产品经理,现独立创业者。关注小红书[「杰克西|硅基杠杆」](https://www.xiaohongshu.com/user/profile/5a1bdc1e4eacab4aa39ea6d6),持续获取我的 AI Agent 观点和思考。
98
-
99
106
  ## 三种运行模式
100
107
 
101
108
  | 模式 | 方法 | 适用场景 |
@@ -104,12 +111,6 @@ Tokens: 12847 output tokens
104
111
  | 自动编排团队 | `runTeam()` | 给一个目标,框架自动规划和执行 |
105
112
  | 显式任务管线 | `runTasks()` | 你自己定义任务图和分配 |
106
113
 
107
- ## 贡献者
108
-
109
- <a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
110
- <img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent" />
111
- </a>
112
-
113
114
  ## 示例
114
115
 
115
116
  所有示例都是可运行脚本,位于 [`examples/`](./examples/) 目录。使用 `npx tsx` 运行:
@@ -127,8 +128,12 @@ npx tsx examples/01-single-agent.ts
127
128
  | [05 — Copilot](examples/05-copilot-test.ts) | GitHub Copilot 作为 LLM 提供者 |
128
129
  | [06 — 本地模型](examples/06-local-model.ts) | Ollama + Claude 混合流水线,通过 `baseURL` 接入(兼容 vLLM、LM Studio 等) |
129
130
  | [07 — 扇出聚合](examples/07-fan-out-aggregate.ts) | `runParallel()` MapReduce — 3 个分析师并行,然后综合 |
130
- | [08 — Gemma 4 本地](examples/08-gemma4-local.ts) | 纯本地 Gemma 4 智能体团队 + tool-calling — 零 API 费用 |
131
- | [09 — Gemma 4 自动编排](examples/09-gemma4-auto-orchestration.ts) | `runTeam()` Gemma 4 coordinator — 自动任务拆解,完全本地 |
131
+ | [08 — Gemma 4 本地](examples/08-gemma4-local.ts) | `runTasks()` + `runTeam()` 本地 Gemma 4 via Ollama — 零 API 费用 |
132
+ | [09 — 结构化输出](examples/09-structured-output.ts) | `outputSchema`(Zod)— 校验 JSON 输出,通过 `result.structured` 获取 |
133
+ | [10 — 任务重试](examples/10-task-retry.ts) | `maxRetries` / `retryDelayMs` / `retryBackoff` + `task_retry` 进度事件 |
134
+ | [11 — 可观测性](examples/11-trace-observability.ts) | `onTrace` 回调 — LLM 调用、工具、任务、智能体的结构化 span 事件 |
135
+ | [12 — Grok](examples/12-grok.ts) | 同示例 02(`runTeam()` 团队协作),使用 Grok(`XAI_API_KEY`) |
136
+ | [13 — Gemini](examples/13-gemini.ts) | Gemini 适配器测试,使用 `gemini-2.5-flash`(`GEMINI_API_KEY`) |
132
137
 
133
138
  ## 架构
134
139
 
@@ -162,6 +167,8 @@ npx tsx examples/01-single-agent.ts
162
167
  │ - stream() │ │ - AnthropicAdapter │
163
168
  └────────┬──────────┘ │ - OpenAIAdapter │
164
169
  │ │ - CopilotAdapter │
170
+ │ │ - GeminiAdapter │
171
+ │ │ - GrokAdapter │
165
172
  │ └──────────────────────┘
166
173
  ┌────────▼──────────┐
167
174
  │ AgentRunner │ ┌──────────────────────┐
@@ -187,28 +194,81 @@ npx tsx examples/01-single-agent.ts
187
194
  |----------|------|----------|------|
188
195
  | Anthropic (Claude) | `provider: 'anthropic'` | `ANTHROPIC_API_KEY` | 已验证 |
189
196
  | OpenAI (GPT) | `provider: 'openai'` | `OPENAI_API_KEY` | 已验证 |
197
+ | Grok (xAI) | `provider: 'grok'` | `XAI_API_KEY` | 已验证 |
190
198
  | GitHub Copilot | `provider: 'copilot'` | `GITHUB_TOKEN` | 已验证 |
199
+ | Gemini | `provider: 'gemini'` | `GEMINI_API_KEY` | 已验证 |
191
200
  | Ollama / vLLM / LM Studio | `provider: 'openai'` + `baseURL` | — | 已验证 |
201
+ | llama.cpp server | `provider: 'openai'` + `baseURL` | — | 已验证 |
192
202
 
193
203
  已验证支持 tool-calling 的本地模型:**Gemma 4**(见[示例 08](examples/08-gemma4-local.ts))。
194
204
 
195
- 任何 OpenAI 兼容 API 均可通过 `provider: 'openai'` + `baseURL` 接入(DeepSeek、Groq、Mistral、Qwen、MiniMax 等)。这些 Provider 尚未完整验证——欢迎通过 [#25](https://github.com/JackChen-me/open-multi-agent/issues/25) 贡献验证。
205
+ 任何 OpenAI 兼容 API 均可通过 `provider: 'openai'` + `baseURL` 接入(DeepSeek、Groq、Mistral、Qwen、MiniMax 等)。**Grok 现已原生支持**,使用 `provider: 'grok'`。
206
+
207
+ ### 本地模型 Tool-Calling
208
+
209
+ 框架支持通过 Ollama、vLLM、LM Studio 或 llama.cpp 运行的本地模型进行 tool-calling。Tool-calling 由这些服务通过 OpenAI 兼容 API 原生处理。
210
+
211
+ **已验证模型:** Gemma 4、Llama 3.1、Qwen 3、Mistral、Phi-4。完整列表见 [ollama.com/search?c=tools](https://ollama.com/search?c=tools)。
212
+
213
+ **兜底提取:** 如果本地模型以文本形式返回工具调用,而非使用 `tool_calls` 协议格式(常见于 thinking 模型或配置不当的服务),框架会自动从文本输出中提取。
214
+
215
+ **超时设置:** 本地推理可能较慢。使用 `AgentConfig` 上的 `timeoutMs` 防止无限等待:
216
+
217
+ ```typescript
218
+ const localAgent: AgentConfig = {
219
+ name: 'local',
220
+ model: 'llama3.1',
221
+ provider: 'openai',
222
+ baseURL: 'http://localhost:11434/v1',
223
+ apiKey: 'ollama',
224
+ tools: ['bash', 'file_read'],
225
+ timeoutMs: 120_000, // 2 分钟后中止
226
+ }
227
+ ```
228
+
229
+ **常见问题:**
230
+ - 模型不调用工具?确保该模型出现在 Ollama 的 [Tools 分类](https://ollama.com/search?c=tools)中。并非所有模型都支持 tool-calling。
231
+ - 使用 Ollama?更新到最新版(`ollama update`)——旧版本有已知的 tool-calling bug。
232
+ - 代理干扰?本地服务使用 `no_proxy=localhost`。
233
+
234
+ ### LLM 配置示例
235
+
236
+ ```typescript
237
+ const grokAgent: AgentConfig = {
238
+ name: 'grok-agent',
239
+ provider: 'grok',
240
+ model: 'grok-4',
241
+ systemPrompt: 'You are a helpful assistant.',
242
+ }
243
+ ```
244
+
245
+ (设置 `XAI_API_KEY` 环境变量即可,无需 `baseURL`。)
196
246
 
197
247
  ## 参与贡献
198
248
 
199
249
  欢迎提 Issue、功能需求和 PR。以下方向的贡献尤其有价值:
200
250
 
201
- - **Provider 集成** — 验证并文档化 OpenAI 兼容 Provider(DeepSeek、Groq、Qwen、MiniMax 等)通过 `baseURL` 接入。详见 [#25](https://github.com/JackChen-me/open-multi-agent/issues/25)。对于非 OpenAI 兼容的 Provider(如 Gemini),欢迎贡献新的 `LLMAdapter` 实现——接口只需两个方法:`chat()` 和 `stream()`。
251
+ - **Provider 集成** — 验证并文档化 OpenAI 兼容 Provider(DeepSeek、Groq、Qwen、MiniMax 等)通过 `baseURL` 接入。详见 [#25](https://github.com/JackChen-me/open-multi-agent/issues/25)。对于非 OpenAI 兼容的 Provider,欢迎贡献新的 `LLMAdapter` 实现——接口只需两个方法:`chat()` 和 `stream()`。
202
252
  - **示例** — 真实场景的工作流和用例。
203
253
  - **文档** — 指南、教程和 API 文档。
204
254
 
255
+ ## 作者
256
+
257
+ > JackChen — 前 WPS 产品经理,现独立创业者。关注小红书[「杰克西|硅基杠杆」](https://www.xiaohongshu.com/user/profile/5a1bdc1e4eacab4aa39ea6d6),持续获取我的 AI Agent 观点和思考。
258
+
259
+ ## 贡献者
260
+
261
+ <a href="https://github.com/JackChen-me/open-multi-agent/graphs/contributors">
262
+ <img src="https://contrib.rocks/image?repo=JackChen-me/open-multi-agent&v=20260405" />
263
+ </a>
264
+
205
265
  ## Star 趋势
206
266
 
207
267
  <a href="https://star-history.com/#JackChen-me/open-multi-agent&Date">
208
268
  <picture>
209
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260403" />
210
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260403" />
211
- <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260403" />
269
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&theme=dark&v=20260405" />
270
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260405" />
271
+ <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=JackChen-me/open-multi-agent&type=Date&v=20260405" />
212
272
  </picture>
213
273
  </a>
214
274
 
@@ -25,6 +25,7 @@
25
25
  import type { AgentConfig, AgentState, AgentRunResult, LLMMessage, StreamEvent, ToolUseContext } from '../types.js';
26
26
  import type { ToolDefinition as FrameworkToolDefinition, ToolRegistry } from '../tool/framework.js';
27
27
  import type { ToolExecutor } from '../tool/executor.js';
28
+ import { type RunOptions } from './runner.js';
28
29
  /**
29
30
  * High-level wrapper around {@link AgentRunner} that manages conversation
30
31
  * history, state transitions, and tool lifecycle.
@@ -61,7 +62,7 @@ export declare class Agent {
61
62
  *
62
63
  * Use this for one-shot queries where past context is irrelevant.
63
64
  */
64
- run(prompt: string): Promise<AgentRunResult>;
65
+ run(prompt: string, runOptions?: Partial<RunOptions>): Promise<AgentRunResult>;
65
66
  /**
66
67
  * Run `prompt` as part of the ongoing conversation.
67
68
  *
@@ -104,6 +105,8 @@ export declare class Agent {
104
105
  * Handles state transitions and error wrapping.
105
106
  */
106
107
  private executeRun;
108
+ /** Emit an `agent` trace event if `onTrace` is provided. */
109
+ private emitAgentTrace;
107
110
  /**
108
111
  * Validate agent output against the configured `outputSchema`.
109
112
  * On first validation failure, retry once with error feedback.
@@ -114,6 +117,17 @@ export declare class Agent {
114
117
  * Handles state transitions and error wrapping.
115
118
  */
116
119
  private executeStream;
120
+ /** Extract the prompt text from the last user message to build hook context. */
121
+ private buildBeforeRunHookContext;
122
+ /**
123
+ * Apply a (possibly modified) hook context back to the messages array.
124
+ *
125
+ * Only text blocks in the last user message are replaced; non-text content
126
+ * (images, tool results) is preserved. The array element is replaced (not
127
+ * mutated in place) so that shallow copies of the original array (e.g. from
128
+ * `prompt()`) are not affected.
129
+ */
130
+ private applyHookContext;
117
131
  private transitionTo;
118
132
  private transitionToError;
119
133
  private toAgentRunResult;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EAEX,cAAc,EACf,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,cAAc,IAAI,uBAAuB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AA0BvD;;;GAGG;AACH,qBAAa,KAAK;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAE5B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,cAAc,CAAmB;IAEzC;;;;;;;OAOG;gBAED,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY;IAkB5B;;;;;OAKG;YACW,SAAS;IA0CvB;;;;;;;OAOG;IACG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQlD;;;;;;;OAOG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBtD;;;;OAIG;IACI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC;IAY1D,oFAAoF;IACpF,QAAQ,IAAI,UAAU;IAItB,uDAAuD;IACvD,UAAU,IAAI,UAAU,EAAE;IAI1B;;;OAGG;IACH,KAAK,IAAI,IAAI;IAab;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI;IAI5C;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,0DAA0D;IAC1D,QAAQ,IAAI,MAAM,EAAE;IAQpB;;;OAGG;YACW,UAAU;IAyCxB;;;OAGG;YACW,wBAAwB;IA+EtC;;;OAGG;YACY,aAAa;IA+B5B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAmBxB;;;OAGG;IACH,gBAAgB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,cAAc;CAU5D"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/agent/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,cAAc,EAEd,UAAU,EACV,WAAW,EAEX,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,OAAO,KAAK,EAAE,cAAc,IAAI,uBAAuB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,EAAmC,KAAK,UAAU,EAAkB,MAAM,aAAa,CAAA;AAqC9F;;;GAGG;AACH,qBAAa,KAAK;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAE5B,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAc;IAC5C,OAAO,CAAC,cAAc,CAAmB;IAEzC;;;;;;;OAOG;gBAED,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY;IAkB5B;;;;;OAKG;YACW,SAAS;IA2CvB;;;;;;;OAOG;IACG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,cAAc,CAAC;IAQpF;;;;;;;OAOG;IAEG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkBtD;;;;OAIG;IAEI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC;IAY1D,oFAAoF;IACpF,QAAQ,IAAI,UAAU;IAItB,uDAAuD;IACvD,UAAU,IAAI,UAAU,EAAE;IAI1B;;;OAGG;IACH,KAAK,IAAI,IAAI;IAab;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI;IAI5C;;;OAGG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAI9B,0DAA0D;IAC1D,QAAQ,IAAI,MAAM,EAAE;IAQpB;;;OAGG;YACW,UAAU;IAuFxB,4DAA4D;IAC5D,OAAO,CAAC,cAAc;IAqBtB;;;OAGG;YACW,wBAAwB;IA+EtC;;;OAGG;YACY,aAAa;IAiD5B,gFAAgF;IAChF,OAAO,CAAC,yBAAyB;IAgBjC;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAmBxB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAoBxB;;;OAGG;IACH,gBAAgB,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,cAAc;CAU5D"}