@migor/agentia 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.
- package/LICENSE +21 -0
- package/README.en.md +144 -0
- package/README.md +202 -76
- package/dist/AGENTS.md +811 -0
- package/dist/container/container.d.ts +10 -2
- package/dist/container/container.js +27 -3
- package/dist/container/container.js.map +1 -1
- package/dist/core/abort.d.ts +10 -0
- package/dist/core/abort.js +28 -0
- package/dist/core/abort.js.map +1 -0
- package/dist/core/blackboard.d.ts +37 -0
- package/dist/core/blackboard.js +2 -0
- package/dist/core/blackboard.js.map +1 -0
- package/dist/core/json.d.ts +2 -0
- package/dist/core/json.js +4 -0
- package/dist/core/json.js.map +1 -1
- package/dist/core/run.d.ts +18 -0
- package/dist/core/run.js +2 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/schema.js +2 -2
- package/dist/core/schema.js.map +1 -1
- package/dist/core/tool.d.ts +62 -7
- package/dist/core/trace.d.ts +20 -4
- package/dist/engine/budget.d.ts +49 -0
- package/dist/engine/budget.js +30 -0
- package/dist/engine/budget.js.map +1 -0
- package/dist/engine/concurrency.d.ts +43 -0
- package/dist/engine/concurrency.js +95 -0
- package/dist/engine/concurrency.js.map +1 -0
- package/dist/engine/errors.d.ts +2 -0
- package/dist/engine/errors.js +7 -0
- package/dist/engine/errors.js.map +1 -1
- package/dist/engine/loop.d.ts +35 -10
- package/dist/engine/loop.js +336 -66
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/policy.d.ts +9 -1
- package/dist/engine/policy.js +8 -5
- package/dist/engine/policy.js.map +1 -1
- package/dist/engine/replay.d.ts +8 -5
- package/dist/engine/replay.js +30 -29
- package/dist/engine/replay.js.map +1 -1
- package/dist/engine/retry.d.ts +47 -0
- package/dist/engine/retry.js +51 -0
- package/dist/engine/retry.js.map +1 -0
- package/dist/engine/spec.d.ts +61 -0
- package/dist/{run → engine}/spec.js +4 -1
- package/dist/engine/spec.js.map +1 -0
- package/dist/engine/tracer.d.ts +9 -0
- package/dist/engine/tracer.js +57 -1
- package/dist/engine/tracer.js.map +1 -1
- package/dist/engine/{context.d.ts → trimming.d.ts} +19 -20
- package/dist/engine/trimming.js +238 -0
- package/dist/engine/trimming.js.map +1 -0
- package/dist/engine/types.d.ts +109 -13
- package/dist/engine/types.js +9 -1
- package/dist/engine/types.js.map +1 -1
- package/dist/engine/usage.d.ts +28 -2
- package/dist/engine/usage.js +39 -6
- package/dist/engine/usage.js.map +1 -1
- package/dist/eval/defineEval.d.ts +73 -0
- package/dist/eval/defineEval.js +44 -0
- package/dist/eval/defineEval.js.map +1 -0
- package/dist/eval/scripted.d.ts +26 -0
- package/dist/eval/scripted.js +43 -0
- package/dist/eval/scripted.js.map +1 -0
- package/dist/index.d.ts +60 -35
- package/dist/index.js +38 -20
- package/dist/index.js.map +1 -1
- package/dist/integrations/anthropic.d.ts +53 -0
- package/dist/integrations/anthropic.js +24 -0
- package/dist/integrations/anthropic.js.map +1 -0
- package/dist/integrations/mcp.d.ts +79 -0
- package/dist/integrations/mcp.js +108 -0
- package/dist/integrations/mcp.js.map +1 -0
- package/dist/integrations/metrics.d.ts +131 -0
- package/dist/integrations/metrics.js +488 -0
- package/dist/integrations/metrics.js.map +1 -0
- package/dist/{run → integrations}/openai.d.ts +12 -5
- package/dist/integrations/openai.js +386 -0
- package/dist/integrations/openai.js.map +1 -0
- package/dist/integrations/otlp.js.map +1 -0
- package/dist/integrations/report.d.ts +78 -0
- package/dist/integrations/report.js +257 -0
- package/dist/integrations/report.js.map +1 -0
- package/dist/runtime/context.d.ts +25 -0
- package/dist/{run → runtime}/context.js +8 -1
- package/dist/runtime/context.js.map +1 -0
- package/dist/{run → runtime}/memory.d.ts +1 -1
- package/dist/{run → runtime}/memory.js +3 -1
- package/dist/runtime/memory.js.map +1 -0
- package/dist/{run → runtime}/run.d.ts +22 -5
- package/dist/runtime/run.js +218 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/session.d.ts +27 -0
- package/dist/runtime/session.js +16 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/{run → runtime}/spec.d.ts +16 -2
- package/dist/runtime/spec.js +28 -0
- package/dist/runtime/spec.js.map +1 -0
- package/dist/{run → runtime}/systemPrompt.d.ts +12 -0
- package/dist/{run → runtime}/systemPrompt.js +16 -3
- package/dist/runtime/systemPrompt.js.map +1 -0
- package/dist/{run → runtime}/types.js.map +1 -1
- package/dist/{run → store}/fsStore.d.ts +15 -0
- package/dist/{run → store}/fsStore.js +43 -1
- package/dist/store/fsStore.js.map +1 -0
- package/dist/{run → store}/redisStore.d.ts +19 -1
- package/dist/{run → store}/redisStore.js +33 -6
- package/dist/store/redisStore.js.map +1 -0
- package/dist/{run → store}/sqliteStore.js +22 -1
- package/dist/store/sqliteStore.js.map +1 -0
- package/dist/{run → store}/store.d.ts +25 -3
- package/dist/store/store.js +63 -0
- package/dist/store/store.js.map +1 -0
- package/dist/toolkit/asset.d.ts +7 -6
- package/dist/toolkit/asset.js +7 -6
- package/dist/toolkit/asset.js.map +1 -1
- package/dist/toolkit/collect.d.ts +20 -7
- package/dist/toolkit/collect.js +21 -7
- package/dist/toolkit/collect.js.map +1 -1
- package/dist/toolkit/discover.d.ts +21 -1
- package/dist/toolkit/discover.js +59 -12
- package/dist/toolkit/discover.js.map +1 -1
- package/dist/toolkit/middleware.d.ts +10 -10
- package/dist/toolkit/middleware.js +17 -4
- package/dist/toolkit/middleware.js.map +1 -1
- package/dist/toolkit/module.d.ts +100 -34
- package/dist/toolkit/module.js +112 -36
- package/dist/toolkit/module.js.map +1 -1
- package/dist/toolkit/prompt.d.ts +4 -6
- package/dist/toolkit/prompt.js +11 -10
- package/dist/toolkit/prompt.js.map +1 -1
- package/dist/toolkit/skill.d.ts +14 -16
- package/dist/toolkit/skill.js +32 -25
- package/dist/toolkit/skill.js.map +1 -1
- package/dist/toolkit/subagent.d.ts +10 -12
- package/dist/toolkit/subagent.js +23 -21
- package/dist/toolkit/subagent.js.map +1 -1
- package/dist/toolkit/tool.d.ts +19 -11
- package/dist/toolkit/tool.js +11 -8
- package/dist/toolkit/tool.js.map +1 -1
- package/dist/toolkit/zod.d.ts +4 -3
- package/dist/toolkit/zod.js +2 -1
- package/dist/toolkit/zod.js.map +1 -1
- package/dist/transport/async.d.ts +133 -0
- package/dist/transport/async.js +415 -0
- package/dist/transport/async.js.map +1 -0
- package/dist/transport/http.d.ts +146 -0
- package/dist/transport/http.js +387 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/{run → transport}/scheduler.d.ts +9 -1
- package/dist/transport/scheduler.js +133 -0
- package/dist/transport/scheduler.js.map +1 -0
- package/dist/transport/sse.d.ts +43 -0
- package/dist/transport/sse.js +51 -0
- package/dist/transport/sse.js.map +1 -0
- package/dist/{run → transport}/transport.d.ts +1 -1
- package/dist/{run → transport}/transport.js +1 -1
- package/dist/transport/transport.js.map +1 -0
- package/package.json +24 -9
- package/dist/engine/context.js +0 -146
- package/dist/engine/context.js.map +0 -1
- package/dist/run/async.d.ts +0 -59
- package/dist/run/async.js +0 -201
- package/dist/run/async.js.map +0 -1
- package/dist/run/context.d.ts +0 -16
- package/dist/run/context.js.map +0 -1
- package/dist/run/fsStore.js.map +0 -1
- package/dist/run/http.d.ts +0 -47
- package/dist/run/http.js +0 -119
- package/dist/run/http.js.map +0 -1
- package/dist/run/memory.js.map +0 -1
- package/dist/run/openai.js +0 -181
- package/dist/run/openai.js.map +0 -1
- package/dist/run/otlp.js.map +0 -1
- package/dist/run/redisStore.js.map +0 -1
- package/dist/run/run.js +0 -129
- package/dist/run/run.js.map +0 -1
- package/dist/run/scheduler.js +0 -85
- package/dist/run/scheduler.js.map +0 -1
- package/dist/run/spec.js.map +0 -1
- package/dist/run/sqliteStore.js.map +0 -1
- package/dist/run/store.js +0 -28
- package/dist/run/store.js.map +0 -1
- package/dist/run/systemPrompt.js.map +0 -1
- package/dist/run/transport.js.map +0 -1
- /package/dist/{run → integrations}/otlp.d.ts +0 -0
- /package/dist/{run → integrations}/otlp.js +0 -0
- /package/dist/{run → runtime}/types.d.ts +0 -0
- /package/dist/{run → runtime}/types.js +0 -0
- /package/dist/{run → store}/sqliteStore.d.ts +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 retrychx
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Agentia
|
|
2
|
+
|
|
3
|
+
[](https://github.com/retrychx/agentia/actions/workflows/ci.yml) [](LICENSE)
|
|
4
|
+
|
|
5
|
+
[中文 README](./README.md) · **English**
|
|
6
|
+
|
|
7
|
+
**A declarative framework for building production agent services.** You declare four kinds of capability
|
|
8
|
+
with decorators + DI and a main agent orchestrates them; every run yields structured output and an
|
|
9
|
+
observable call tree (trace, cost, metrics).
|
|
10
|
+
|
|
11
|
+
> This is a **summary**. The authoritative and always-current documentation is Chinese:
|
|
12
|
+
> [`docs/usage-guide.md`](./docs/usage-guide.md) (API reference, type wiring, known limits) and the
|
|
13
|
+
> [website](https://agentia-web.pages.dev). We keep this file short on purpose — a hand-maintained
|
|
14
|
+
> full translation drifts.
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
Node.js **≥ 18** (the only `engines` requirement; CI runs 18 / 20 / 22). Deno and edge runtimes are
|
|
19
|
+
**not** validated. The only store touching a Node builtin is `SqliteTaskStore` (needs Node ≥ 22.5 for
|
|
20
|
+
`node:sqlite`) — it fails with a readable error at construction time, and never breaks importing the package.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm i @migor/agentia # the framework
|
|
26
|
+
npm i -g @migor/cli # CLI: scaffold / generate / dev inspector
|
|
27
|
+
export ANTHROPIC_API_KEY=sk-... # or ANTHROPIC_AUTH_TOKEN; ANTHROPIC_BASE_URL for compatible gateways
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
### A. CLI
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
agentia create my-app
|
|
36
|
+
cd my-app && npm install
|
|
37
|
+
agentia g tool weather # create src/tools/weather/index.ts and register it
|
|
38
|
+
agentia dev # tsx watch + local inspector panel
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Four self-describing directories hold capabilities — the directory name **is** the kind:
|
|
42
|
+
`src/tools/` · `src/skills/` · `src/prompts/` · `src/subagents/`; the registry is `src/registry.ts`.
|
|
43
|
+
|
|
44
|
+
### B. By hand
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import { Tool, createApp, SystemPrompt } from '@migor/agentia';
|
|
48
|
+
|
|
49
|
+
class WeatherTools {
|
|
50
|
+
@Tool({
|
|
51
|
+
description: 'Look up the weather for a city',
|
|
52
|
+
schema: {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: { city: { type: 'string' } },
|
|
55
|
+
required: ['city'],
|
|
56
|
+
additionalProperties: false,
|
|
57
|
+
},
|
|
58
|
+
})
|
|
59
|
+
get_weather(input: { city: string }): string {
|
|
60
|
+
return `city=${input.city}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const app = createApp({
|
|
65
|
+
name: 'weather-app',
|
|
66
|
+
providers: [{ provide: 'weather', useClass: WeatherTools }],
|
|
67
|
+
system: new SystemPrompt().add('role', 'You are a helpful weather assistant.', true),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const { result } = await app.run([{ role: 'user', content: 'Weather in Shanghai?' }]);
|
|
71
|
+
console.log(result.finalText); // final text
|
|
72
|
+
console.log(result.trace); // call tree + per-step tokens/cost (traceId === runId)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or point `createApp` at the directories instead of passing providers:
|
|
76
|
+
`createApp({ discover: ['src/tools', 'src/skills', 'src/prompts', 'src/subagents'], system })`.
|
|
77
|
+
|
|
78
|
+
## The four capability kinds
|
|
79
|
+
|
|
80
|
+
The model picks from one shared "menu" by `description`; the decorator decides **who controls the flow**:
|
|
81
|
+
|
|
82
|
+
| Kind | Decorator | Who controls the flow | Typical use |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| Tool | `@Tool` | your code (one call = one function) | deterministic work: DB, math, HTTP |
|
|
85
|
+
| Skill | `@Skill` | your code (scripted; model calls only at explicit `ctx.llm()`) | fixed "fetch → let the model write → post-process" pipelines |
|
|
86
|
+
| Sub-agent | `@SubAgent` | **the model** (own loop, trimmed context) | multi-step autonomy without polluting the main context |
|
|
87
|
+
| Prompt asset | `@Prompt` | pulled by the model on demand | long specs/templates that shouldn't sit in context by default |
|
|
88
|
+
|
|
89
|
+
## Runtime features
|
|
90
|
+
|
|
91
|
+
- **Triggering** — `app.run()` (sync RPC) · `AsyncRunner` (idempotency-keyed, retryable, resumable via a
|
|
92
|
+
store) · `Scheduler` (cron-like) · `createHttpHandler` (`POST /run`, `POST /tasks`, `GET /tasks/:id`,
|
|
93
|
+
`GET /healthz`, optional `GET /metrics`, graceful `drain()`)
|
|
94
|
+
- **Context budget** — `createBudgetPolicy({ budgetTokens, summarize })`
|
|
95
|
+
- **Hard cost caps** — `maxTotalTokens` / `maxCostUsd` (+ `priceOverrides` to price non-Anthropic models)
|
|
96
|
+
- **Structured output** — `resultSchema`; `result.typed` is validated, or use `fromZod<T>()` for full type inference
|
|
97
|
+
- **Middleware** — an onion chain around every capability call (auth, rate limiting, caching, audit)
|
|
98
|
+
- **Cancellation / retries / streaming / tool concurrency** — `signal`, retry policy, `onText`, `maxToolConcurrency`
|
|
99
|
+
|
|
100
|
+
## Observability & cost
|
|
101
|
+
|
|
102
|
+
One run == one trace (`traceId === runId`), **built in from turn 0** — not a bolt-on third-party tracing SDK:
|
|
103
|
+
|
|
104
|
+
- **Per-step accounting** — every span carries model, input/output/cache tokens, cost estimate, status and error type
|
|
105
|
+
- **One seam out** — `TraceSink { export(trace) }`, delivered on **both** the success and failure paths; a throwing
|
|
106
|
+
sink never breaks the run. Persistence / sampling / redaction are composed outside the seam
|
|
107
|
+
(`examples/observability/`, [`docs/observability.md`](./docs/observability.md))
|
|
108
|
+
- **Cost you can cap** — `priceOverrides` patches the price table; unpriced models emit an explicit
|
|
109
|
+
`usage.unpriced` event (never a silent zero); `maxCostUsd` / `maxTotalTokens` stop the run
|
|
110
|
+
- **Replay** — `traceToMessages(trace)` linearises a finished trace back into model messages
|
|
111
|
+
- **Export** — `createOtlpExporter({ endpoint })`; `metricsSink()` (Prometheus text or OTLP metrics), zero dependency
|
|
112
|
+
- **Locally visible** — `agentia dev` opens an inspector panel sharing one renderer with the website Playground;
|
|
113
|
+
`agentia report <trace.jsonl>` ranks which capability is slow / expensive / error-prone
|
|
114
|
+
|
|
115
|
+
## Integrations
|
|
116
|
+
|
|
117
|
+
- **Models** — `createAnthropicClient()` (default) and `createOpenAIClient()` for any OpenAI-compatible
|
|
118
|
+
endpoint (DeepSeek, **Ollama**, gateways). You never need to touch a vendor SDK: pass
|
|
119
|
+
`createAnthropicClient({ baseURL })` / `createOpenAIClient({ baseURL })`.
|
|
120
|
+
- **MCP** — `mcpTools()` bridges an MCP server's tools into the menu (duck-typed, zero dependency)
|
|
121
|
+
- **Memory** — `memory: { store, keys }` for cross-run state; task stores: memory / JSONL / SQLite / Redis
|
|
122
|
+
- **Evals** — `scriptedClient` + `defineEval` turn mocked runs into a first-class diagnostic loop
|
|
123
|
+
- **Platforms** — send traces to Langfuse / Phoenix / etc. via OTLP or a tiny custom `TraceSink`
|
|
124
|
+
(see [`docs/observability.md`](./docs/observability.md) §2.6)
|
|
125
|
+
|
|
126
|
+
## Documentation
|
|
127
|
+
|
|
128
|
+
| | |
|
|
129
|
+
|---|---|
|
|
130
|
+
| Usage guide (authoritative, zh) | [`docs/usage-guide.md`](./docs/usage-guide.md) |
|
|
131
|
+
| Production observability recipes | [`docs/observability.md`](./docs/observability.md) |
|
|
132
|
+
| Examples (complete app / minimal deploy / observability) | [`examples/`](./examples/) |
|
|
133
|
+
| Design spec & roadmap | [`docs/spec.md`](./docs/spec.md) · [`docs/roadmap.md`](./docs/roadmap.md) |
|
|
134
|
+
| Website · Playground | [agentia-web.pages.dev](https://agentia-web.pages.dev) · [playground](https://agentia-web.pages.dev/playground.html) |
|
|
135
|
+
|
|
136
|
+
## Contributing
|
|
137
|
+
|
|
138
|
+
See [`CONTRIBUTING.md`](./CONTRIBUTING.md) — and note that [`AGENTS.md`](./AGENTS.md) is the single
|
|
139
|
+
source for this repo's engineering conventions. Security issues: [`SECURITY.md`](./SECURITY.md)
|
|
140
|
+
(please don't open a public issue).
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
[MIT](./LICENSE)
|
package/README.md
CHANGED
|
@@ -1,44 +1,66 @@
|
|
|
1
1
|
# Agentia
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[中文](./README.md) · [English](./README.en.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://github.com/retrychx/agentia/actions/workflows/ci.yml) [](LICENSE)
|
|
6
|
+
|
|
7
|
+
面向应用开发的声明式 agent 服务开发框架:装饰器 + DI 声明四类能力,主 agent 编排执行;每次 run 产出结构化结果与可观测调用树(trace、成本、指标),交付可直接上线的服务。
|
|
8
|
+
|
|
9
|
+
- [安装与配置](#安装与配置)
|
|
10
|
+
- [快速开始](#快速开始)
|
|
11
|
+
- [四类能力](#四类能力)
|
|
12
|
+
- [运行时特性](#运行时特性)
|
|
13
|
+
- [可观测性与成本](#可观测性与成本)
|
|
14
|
+
- [集成](#集成)
|
|
15
|
+
- [API 速查](#api-速查)
|
|
16
|
+
- [开发本仓库](#开发本仓库)
|
|
17
|
+
- [延伸阅读](#延伸阅读)
|
|
18
|
+
|
|
19
|
+
## 安装与配置
|
|
6
20
|
|
|
7
21
|
```bash
|
|
8
|
-
|
|
22
|
+
npm i @migor/agentia # 框架(项目依赖)
|
|
23
|
+
npm i -g @migor/cli # 命令行工具(脚手架 / 生成 / 调试)
|
|
24
|
+
|
|
25
|
+
export ANTHROPIC_API_KEY=sk-... # 或 ANTHROPIC_AUTH_TOKEN
|
|
9
26
|
# 可选:ANTHROPIC_BASE_URL(兼容端点)、AGENTIA_MODEL(缺省 claude-opus-5)
|
|
10
27
|
```
|
|
11
28
|
|
|
12
|
-
|
|
29
|
+
> **版本**:`0.2.2`(`@migor/agentia` 与 `@migor/cli` 均已发布到 npm)。`examples/` **刻意**用
|
|
30
|
+
> `file:../..` 指向本仓库而不是 npm 版本 —— 跑的是**工作区代码**,理由见
|
|
31
|
+
> [`examples/README.md`](examples/README.md) 的「依赖说明」。
|
|
32
|
+
|
|
33
|
+
> **运行时**:Node ≥ 18(`engines` 唯一要求,CI 在 18/20/22 上守)。按 Node 设计并测试,
|
|
34
|
+
> **未对 Deno / edge 做验证**。唯一碰内置模块的 store 是 `SqliteTaskStore`(需 Node ≥ 22.5 的
|
|
35
|
+
> `node:sqlite`)—— 未提供时**构造期给可读报错**,不影响包本身被导入。
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
## 快速开始
|
|
39
|
+
|
|
40
|
+
两条路线,按需选一即可(也可混用)。
|
|
41
|
+
|
|
42
|
+
### 路线 A:CLI 脚手架
|
|
13
43
|
|
|
14
44
|
```bash
|
|
15
|
-
npm i -g @migor/cli # 安装 CLI(提供 agentia 命令)
|
|
16
45
|
agentia create my-app # 脚手架新项目(依赖 @migor/agentia)
|
|
17
46
|
cd my-app && npm install
|
|
18
|
-
agentia g tool weather # 生成
|
|
19
|
-
agentia g subagent doc-reviewer # 生成
|
|
20
|
-
agentia g skill note-writer # 生成
|
|
21
|
-
agentia g prompt style-guide # 生成
|
|
22
|
-
|
|
47
|
+
agentia g tool weather # 生成 src/tools/weather/index.ts 并登记 src/registry.ts
|
|
48
|
+
agentia g subagent doc-reviewer # 生成 src/subagents/doc-reviewer/{index.ts,system.md}
|
|
49
|
+
agentia g skill note-writer # 生成 src/skills/note-writer/index.ts
|
|
50
|
+
agentia g prompt style-guide # 生成 src/prompts/style-guide/{index.ts,asset.md}
|
|
51
|
+
agentia dev # tsx watch + 本地 inspector 面板
|
|
23
52
|
```
|
|
24
53
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
54
|
+
**目录约定**:四分类目录,一能力一文件夹 —— `src/tools/` · `src/skills/` · `src/prompts/` · `src/subagents/`。
|
|
55
|
+
目录名就是类型,不用记别名。每个文件夹的 `index.ts` default export 一个 provider 类,DI token 缺省 = 文件夹名;
|
|
56
|
+
长文本放文件夹内 `.md`,代码里用 `asset(import.meta.url, './system.md')` 读取。
|
|
28
57
|
|
|
29
|
-
|
|
30
|
-
// 1) 目录扫描:启动期扫描 units/*/ 自动装配(返回 Promise)
|
|
31
|
-
const app = await createApp({ name: 'my-app', discover: 'units', system });
|
|
58
|
+
### 路线 B:手写装配
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
import { providers } from './units.js';
|
|
35
|
-
const app = createApp({ name: 'my-app', providers, system });
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## 手写单元
|
|
60
|
+
不依赖 CLI,直接声明能力并装配成应用:
|
|
39
61
|
|
|
40
62
|
```ts
|
|
41
|
-
import { Tool,
|
|
63
|
+
import { Tool, createApp, SystemPrompt, RunContext } from '@migor/agentia';
|
|
42
64
|
|
|
43
65
|
class WeatherTools {
|
|
44
66
|
// 工具名缺省取方法名(建议 snake_case);入参 = 模型按 schema 解析的结构化 input
|
|
@@ -53,30 +75,17 @@ class WeatherTools {
|
|
|
53
75
|
strict: true,
|
|
54
76
|
})
|
|
55
77
|
get_weather(input: { city: string }): string {
|
|
56
|
-
// 方法体内随时可读本次 run 的上下文(blackboard
|
|
57
|
-
|
|
78
|
+
// 方法体内随时可读本次 run 的上下文(blackboard)。
|
|
79
|
+
// 想让键有补全/校验:在一次 declare module 里合并 Blackboard(见 docs/usage-guide.md §5.1);
|
|
80
|
+
// 未声明时键为 string、值为 unknown,这里按需断言。
|
|
81
|
+
const token = RunContext.current()?.get('authToken') as string | undefined;
|
|
58
82
|
return `city=${input.city};token=${token ?? 'none'}`;
|
|
59
83
|
}
|
|
60
84
|
}
|
|
61
85
|
|
|
62
|
-
class Pipeline {
|
|
63
|
-
// 子 agent:独立循环 + 裁剪上下文,只有最终报告回流主上下文(方法体不执行)
|
|
64
|
-
@SubAgent({
|
|
65
|
-
name: 'reviewer',
|
|
66
|
-
description: '审查给定文档并输出书面评审意见',
|
|
67
|
-
schema: { type: 'object', properties: { doc: { type: 'string' } }, required: ['doc'], additionalProperties: false },
|
|
68
|
-
system: '你是评审 agent。结论必须以“审查通过/不通过”开头。',
|
|
69
|
-
tools: ['weather'], // 子 agent 自己的工具菜单(provider token)
|
|
70
|
-
})
|
|
71
|
-
reviewer(_input: { doc: string }): void {}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
86
|
const app = createApp({
|
|
75
87
|
name: 'weather-app',
|
|
76
|
-
providers: [
|
|
77
|
-
{ provide: 'weather', useClass: WeatherTools },
|
|
78
|
-
{ provide: 'pipeline', useClass: Pipeline },
|
|
79
|
-
],
|
|
88
|
+
providers: [{ provide: 'weather', useClass: WeatherTools }],
|
|
80
89
|
system: new SystemPrompt().add('role', '你是天气助手。', true),
|
|
81
90
|
});
|
|
82
91
|
|
|
@@ -88,9 +97,33 @@ console.log(result.finalText); // 最终文本
|
|
|
88
97
|
console.log(result.trace); // 调用树 + 每步 token/成本(traceId == runId)
|
|
89
98
|
```
|
|
90
99
|
|
|
91
|
-
|
|
100
|
+
装配还有**目录扫描**这条路(与显式注册表可混用):
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// 按给定顺序扫各目录(返回 Promise);也可用 CLI 维护的 src/registry.ts 显式注册
|
|
104
|
+
const app = await createApp({
|
|
105
|
+
name: 'my-app',
|
|
106
|
+
discover: ['src/tools', 'src/skills', 'src/prompts', 'src/subagents'],
|
|
107
|
+
system,
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 四类能力
|
|
112
|
+
|
|
113
|
+
主 agent 按 `description` 从同一张「能力菜单」自选;装饰器只决定**谁控制流程**:
|
|
114
|
+
|
|
115
|
+
| 能力 | 装饰器 | 谁决定流程 | 典型用途 |
|
|
116
|
+
|---|---|---|---|
|
|
117
|
+
| 工具 | `@Tool` | 你的代码(一次调用 = 一个函数) | 确定性操作:查库、算数、调 API |
|
|
118
|
+
| 技能 | `@Skill` | 你的代码(脚本式,显式 `ctx.llm()`) | 「先取数 → 再让模型写 → 再加工」的固定流程 |
|
|
119
|
+
| 子 agent | `@SubAgent` | **模型自己**(独立循环 + 裁剪上下文) | 自主多步、且中间过程不该污染主上下文 |
|
|
120
|
+
| 提示资产 | `@Prompt` | 模型拉取(按需注入的文本) | 长文规范/模板,平时不进上下文 |
|
|
121
|
+
|
|
122
|
+
`@Tool` 的写法见上方路线 B;其余三类:
|
|
92
123
|
|
|
93
124
|
```ts
|
|
125
|
+
import { Skill, SubAgent, Prompt, asset, type SkillContext } from '@migor/agentia';
|
|
126
|
+
|
|
94
127
|
// @Skill:代码控制的流程,模型调用只发生在显式 ctx.llm()
|
|
95
128
|
class Notes {
|
|
96
129
|
@Skill({ description: '按主题整理要点' })
|
|
@@ -100,20 +133,53 @@ class Notes {
|
|
|
100
133
|
}
|
|
101
134
|
}
|
|
102
135
|
|
|
136
|
+
// @SubAgent:独立循环 + 裁剪上下文,只有最终报告回流主上下文(方法体不执行)
|
|
137
|
+
class Pipeline {
|
|
138
|
+
@SubAgent({
|
|
139
|
+
name: 'reviewer',
|
|
140
|
+
description: '审查给定文档并输出书面评审意见',
|
|
141
|
+
schema: { type: 'object', properties: { doc: { type: 'string' } }, required: ['doc'], additionalProperties: false },
|
|
142
|
+
system: '你是评审 agent。结论必须以“审查通过/不通过”开头。',
|
|
143
|
+
tools: ['weather'], // 子 agent 自己的工具菜单(provider token)
|
|
144
|
+
})
|
|
145
|
+
reviewer(_input: { doc: string }): void {}
|
|
146
|
+
}
|
|
147
|
+
|
|
103
148
|
// @Prompt:纯文本资产,模型判定需要时拉取进上下文
|
|
104
149
|
class Assets {
|
|
105
150
|
@Prompt({ description: '品牌基调文案规范' })
|
|
106
151
|
style_guide(): string {
|
|
107
|
-
return asset(import.meta.url, './asset.md'); //
|
|
152
|
+
return asset(import.meta.url, './asset.md'); // 从能力文件夹读 .md
|
|
108
153
|
}
|
|
109
154
|
}
|
|
110
155
|
```
|
|
111
156
|
|
|
112
|
-
|
|
157
|
+
四类一起装配(`providers` 里逐个登记;token 即子 agent / 技能引用工具的菜单名):
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { createApp, SystemPrompt } from '@migor/agentia';
|
|
161
|
+
|
|
162
|
+
const app = createApp({
|
|
163
|
+
name: 'weather-app',
|
|
164
|
+
providers: [
|
|
165
|
+
{ provide: 'weather', useClass: WeatherTools },
|
|
166
|
+
{ provide: 'notes', useClass: Notes },
|
|
167
|
+
{ provide: 'pipeline', useClass: Pipeline },
|
|
168
|
+
{ provide: 'assets', useClass: Assets },
|
|
169
|
+
],
|
|
170
|
+
system: new SystemPrompt().add('role', '你是天气助手。', true),
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## 运行时特性
|
|
175
|
+
|
|
176
|
+
### 触发方式
|
|
113
177
|
|
|
114
178
|
同一份应用,三种触发任选:
|
|
115
179
|
|
|
116
180
|
```ts
|
|
181
|
+
import { AsyncRunner, FileTaskStore, Scheduler } from '@migor/agentia';
|
|
182
|
+
|
|
117
183
|
// 同步 RPC
|
|
118
184
|
const { run, result } = await app.run(messages);
|
|
119
185
|
|
|
@@ -127,7 +193,7 @@ const scheduler = new Scheduler(runner);
|
|
|
127
193
|
scheduler.every(60_000, '巡检一次', { idempotencyKey: 'patrol' });
|
|
128
194
|
```
|
|
129
195
|
|
|
130
|
-
|
|
196
|
+
### 长上下文预算
|
|
131
197
|
|
|
132
198
|
```ts
|
|
133
199
|
import { createBudgetPolicy } from '@migor/agentia';
|
|
@@ -135,22 +201,37 @@ import { createBudgetPolicy } from '@migor/agentia';
|
|
|
135
201
|
const app = createApp({
|
|
136
202
|
// ...
|
|
137
203
|
contextPolicy: createBudgetPolicy({
|
|
138
|
-
budgetTokens: 60_000,
|
|
204
|
+
budgetTokens: 60_000, // 超预算先丢旧工具对,仍超且有 summarize 才压缩
|
|
139
205
|
summarize: (text) => mySummarizer(text), // 可选,框架不替你调模型
|
|
140
206
|
}),
|
|
141
207
|
});
|
|
142
208
|
```
|
|
143
209
|
|
|
144
|
-
|
|
210
|
+
### 结构化结果
|
|
145
211
|
|
|
146
|
-
|
|
212
|
+
```ts
|
|
213
|
+
const { result } = await app.run(messages, {
|
|
214
|
+
resultSchema: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
properties: { pass: { type: 'boolean' }, reason: { type: 'string' } },
|
|
217
|
+
required: ['pass', 'reason'],
|
|
218
|
+
additionalProperties: false,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
console.log(result.typed); // 校验过的结构化结果,不再从文本里猜 JSON
|
|
222
|
+
// schema 也可来自 zod(peer 可选):fromZod(z.toJSONSchema(S), S)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 中间件
|
|
226
|
+
|
|
227
|
+
挂在每一次能力调用前后的洋葱链——鉴权、限流、缓存、审计都走这里:
|
|
147
228
|
|
|
148
229
|
```ts
|
|
149
230
|
const app = createApp({
|
|
150
231
|
// ...
|
|
151
232
|
middleware: [
|
|
152
233
|
async (call, next) => {
|
|
153
|
-
if (call.
|
|
234
|
+
if (call.capability.name === 'danger_op' && !RunContext.current()?.get('isAdmin')) {
|
|
154
235
|
return 'forbidden'; // 短路,不调 next 即拦截
|
|
155
236
|
}
|
|
156
237
|
return next(); // next(newInput) 还可改写入参
|
|
@@ -159,52 +240,86 @@ const app = createApp({
|
|
|
159
240
|
});
|
|
160
241
|
```
|
|
161
242
|
|
|
162
|
-
##
|
|
243
|
+
## 可观测性与成本
|
|
244
|
+
|
|
245
|
+
一次 run == 一条 trace(`traceId === runId`),**Turn 0 起内建** —— 不是外挂的第三方追踪 SDK 集成:
|
|
163
246
|
|
|
164
247
|
```ts
|
|
165
|
-
const { result } = await app.run(messages
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
properties: { pass: { type: 'boolean' }, reason: { type: 'string' } },
|
|
169
|
-
required: ['pass', 'reason'],
|
|
170
|
-
additionalProperties: false,
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
console.log(result.typed); // 校验过的结构化结果,不再从文本里猜 JSON
|
|
174
|
-
// schema 也可来自 zod(peer 可选):fromZod(z.toJSONSchema(S), S)
|
|
248
|
+
const { run, result } = await app.run(messages);
|
|
249
|
+
result.trace.spans; // 调用树:llm.turn / 能力 span / 事件
|
|
250
|
+
result.trace.totalUsage; // token 汇总(只累加 llm.turn;能力 span 是子孙聚合,不参与求和)
|
|
175
251
|
```
|
|
176
252
|
|
|
177
|
-
|
|
253
|
+
- **每步记账**:span 属性带 model、input/output/cache tokens、成本估计、状态、错误类型
|
|
254
|
+
- **出口是一条缝**:`TraceSink { export(trace) }` —— run 收尾(成功/失败两条路径)都投递,sink 抛错不影响 run。落库 / 采样 / 脱敏都在缝外用 sink 组合(实码见 `examples/observability/`,说明见 `docs/observability.md`)
|
|
255
|
+
- **指标**:`metricsSink` 满足 `TraceSink` 即可接入(Prometheus 文本 / OTLP metrics),零依赖
|
|
256
|
+
- **成本**:`priceOverrides` 注入价目表;未定价模型显式发 `usage.unpriced` 事件;`createBudgetGuard` 做**硬管控**(超限 run 以 `budget_exceeded` 收尾、算失败)
|
|
257
|
+
- **调优闭环**:`buildRunReport` 出「能力 / 模型的耗时·token·成本·错误率排行」,CLI `agentia report <trace.jsonl>` 直接渲染
|
|
258
|
+
- **回放**:`traceToMessages` 把已完成的 trace 线性化喂回模型(调试基底)
|
|
259
|
+
- **本地开发**:`agentia dev` 的 inspector 面板与 `@migor/trace-view` 共用同一份渲染器(避免两处漂移)
|
|
260
|
+
- **导出 OTLP**:
|
|
178
261
|
|
|
179
262
|
```ts
|
|
180
|
-
|
|
263
|
+
import { createOtlpExporter } from '@migor/agentia';
|
|
264
|
+
|
|
265
|
+
await createOtlpExporter({ endpoint: 'http://localhost:4318' }).export(result.trace);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
> 权威口径见 `docs/usage-guide.md` 的「观测」与「成本硬管控」两节。
|
|
269
|
+
|
|
270
|
+
## 集成
|
|
271
|
+
|
|
272
|
+
### HTTP 宿主
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
import { createServer } from 'node:http';
|
|
276
|
+
import { createHttpHandler } from '@migor/agentia';
|
|
277
|
+
|
|
278
|
+
// POST /run(同步) POST /tasks(异步) GET /tasks/:id(轮询)
|
|
181
279
|
createServer(createHttpHandler(app, { runner })).listen(8080);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 多模型(OpenAI 兼容端点)
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
import { createOpenAIClient } from '@migor/agentia';
|
|
182
286
|
|
|
183
|
-
// OpenAI 兼容端点(DeepSeek 等)+ 跨 run 记忆
|
|
184
287
|
const { result } = await app.run(messages, {
|
|
185
288
|
client: createOpenAIClient({ baseURL: 'https://api.deepseek.com' }),
|
|
186
289
|
model: 'deepseek-chat',
|
|
187
|
-
memory: { store: new InMemoryMemoryStore(), keys: ['profile'] },
|
|
188
290
|
});
|
|
291
|
+
```
|
|
189
292
|
|
|
190
|
-
|
|
191
|
-
|
|
293
|
+
> **本地模型(Ollama 等)**:Ollama 暴露 OpenAI 兼容端点,用同一个适配器即可 ——
|
|
294
|
+
> `createOpenAIClient({ baseURL: 'http://localhost:11434/v1' })` + `model: 'qwen3'`,
|
|
295
|
+
> **不需要任何新代码或新依赖**。
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
### 跨 run 记忆
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
import { InMemoryMemoryStore } from '@migor/agentia';
|
|
302
|
+
|
|
303
|
+
const { result } = await app.run(messages, {
|
|
304
|
+
memory: { store: new InMemoryMemoryStore(), keys: ['profile'] },
|
|
305
|
+
});
|
|
192
306
|
```
|
|
193
307
|
|
|
194
|
-
##
|
|
308
|
+
## API 速查
|
|
195
309
|
|
|
196
310
|
| 导出 | 用途 |
|
|
197
311
|
|---|---|
|
|
198
|
-
| `createApp` / `discoverProviders` | 装配应用 /
|
|
312
|
+
| `createApp` / `discoverProviders` | 装配应用 / 扫描能力目录 |
|
|
199
313
|
| `defineModule` | 能力包(providers + middleware 打包分发) |
|
|
200
|
-
| `Tool` / `Skill` / `SubAgent` / `Prompt` |
|
|
201
|
-
| `
|
|
202
|
-
| `asset` |
|
|
314
|
+
| `Tool` / `Skill` / `SubAgent` / `Prompt` | 四类能力装饰器 |
|
|
315
|
+
| `CapabilityMiddleware`(`middleware` 选项) | 能力调用拦截器链 |
|
|
316
|
+
| `asset` | 读能力文件夹内的文本资产 |
|
|
203
317
|
| `SystemPrompt` | 拼装系统提示(自动打缓存 breakpoint) |
|
|
204
318
|
| `RunContext.current()` | 取本次 run 的 blackboard / runId |
|
|
205
319
|
| `AsyncRunner` / `Scheduler` / `runSync` / `createHttpHandler` | 异步 / 定时 / 同步 / HTTP 触发 |
|
|
206
320
|
| `FileTaskStore` / `SqliteTaskStore` / `RedisTaskStore` / `InMemoryTaskStore` | 任务记录存储 |
|
|
207
321
|
| `createBudgetPolicy` | 长上下文预算护栏 |
|
|
322
|
+
| `createAnthropicClient` | 默认 ModelClient(Anthropic):自定义只传 `apiKey` / `baseURL`,不必直接依赖厂商 SDK |
|
|
208
323
|
| `createOpenAIClient` | OpenAI 兼容端点适配(多模型) |
|
|
209
324
|
| `InMemoryMemoryStore`(`memory` 选项) | 跨 run 记忆水合/回写 |
|
|
210
325
|
| `createOtlpExporter` | trace 导出 OTLP |
|
|
@@ -212,16 +327,27 @@ await createOtlpExporter({ endpoint: 'http://localhost:4318' }).export(result.tr
|
|
|
212
327
|
| `fromZod` | zod schema 接入(peer 可选) |
|
|
213
328
|
| `runAgent` / `executeRun` | 裸引擎入口(不走装配) |
|
|
214
329
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
## 本仓库脚本
|
|
330
|
+
## 开发本仓库
|
|
218
331
|
|
|
219
332
|
```bash
|
|
220
333
|
npm install
|
|
221
334
|
npm run build # 编译框架(dist/)
|
|
222
335
|
npm run typecheck # 类型检查
|
|
336
|
+
npm run lint # lint + 格式检查(Biome)
|
|
223
337
|
npm test # 单元测试(node:test)
|
|
224
|
-
npm run e2e # 端到端:CLI 脚手架 →
|
|
338
|
+
npm run e2e # 端到端:CLI 脚手架 → 装配 mock run;再真跑 examples/complete 的完整服务
|
|
225
339
|
```
|
|
226
340
|
|
|
227
|
-
>
|
|
341
|
+
> 注:本仓库的 `npm run dev`(tsx)前需先 `npm approve-scripts` 批准 esbuild/tsx 的 postinstall;
|
|
342
|
+
> 脚手架项目里的 `agentia dev` 不受此限。
|
|
343
|
+
|
|
344
|
+
## 延伸阅读
|
|
345
|
+
|
|
346
|
+
- **使用者向完整说明**(API 速查 / 类型链路 / 已知边界 / 反例):[`docs/usage-guide.md`](docs/usage-guide.md)
|
|
347
|
+
- 完整导出清单:[`src/index.ts`](src/index.ts)
|
|
348
|
+
- 设计规格:[`docs/spec.md`](docs/spec.md)
|
|
349
|
+
- 生产可观测配方(落库检索 / 日志关联 / 采样 / 脱敏):[`docs/observability.md`](docs/observability.md)
|
|
350
|
+
- 完整示例(四类能力 + 三种触发 + 全观测栈):[`examples/complete/`](examples/complete/)
|
|
351
|
+
- 最小部署示例:[`examples/deploy/`](examples/deploy/)
|
|
352
|
+
- 方向与状态:[`docs/roadmap.md`](docs/roadmap.md)
|
|
353
|
+
- 官网:[agentia-web.pages.dev](https://agentia-web.pages.dev)([在线 Playground](https://agentia-web.pages.dev/playground.html) · [文档](https://agentia-web.pages.dev/docs.html))
|