@namzu/sdk 29.0.0 → 30.0.1
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/CHANGELOG.md +50 -0
- package/README.md +57 -419
- package/dist/plugin/loader.d.ts.map +1 -1
- package/dist/plugin/loader.js +10 -12
- package/dist/plugin/loader.js.map +1 -1
- package/dist/public-runtime.d.ts +14 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +14 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +10 -12
- package/dist/skills/loader.js.map +1 -1
- package/dist/utils/log/create-logger.d.ts +3 -3
- package/dist/utils/log/create-logger.d.ts.map +1 -1
- package/dist/utils/log/create-logger.js +10 -8
- package/dist/utils/log/create-logger.js.map +1 -1
- package/dist/utils/log/process-sink.d.ts +7 -4
- package/dist/utils/log/process-sink.d.ts.map +1 -1
- package/dist/utils/log/process-sink.js +19 -13
- package/dist/utils/log/process-sink.js.map +1 -1
- package/dist/utils/log/types.d.ts +12 -7
- package/dist/utils/log/types.d.ts.map +1 -1
- package/dist/utils/log/types.js +6 -6
- package/dist/utils/log/types.js.map +1 -1
- package/dist/utils/logger.d.ts +15 -35
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +18 -136
- package/dist/utils/logger.js.map +1 -1
- package/package.json +1 -1
- package/src/plugin/loader.ts +10 -12
- package/src/public-runtime.ts +14 -1
- package/src/skills/loader.ts +10 -12
- package/src/utils/log/create-logger.ts +10 -8
- package/src/utils/log/process-sink.ts +19 -13
- package/src/utils/log/types.ts +18 -13
- package/src/utils/logger.ts +18 -159
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 30.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b2c005c: Make each README an npm package page rather than the package's manual.
|
|
8
|
+
|
|
9
|
+
`@namzu/sdk`'s README was a twenty-four-section architecture tour, 45 KB of it; the others ran to several hundred lines each. That is the right shape for a single-package repository, where the README _is_ the documentation, and the wrong one here — it duplicated a `docs/` tree that already existed, and nothing checked that the two agreed.
|
|
10
|
+
|
|
11
|
+
Each README is now what a reader needs in the first minute: what the package is, install with its Node requirement, one working example, and links. The long-form material moved into `docs/` whole — `docs/sdk/architecture.md`, `docs/cli/reference.md`, `docs/packages/<name>.md` — where the doc gates cover it.
|
|
12
|
+
|
|
13
|
+
Two documentation defects fell out of the move, both in `@namzu/telemetry`'s session-export example, and both had been shipping: the config field is `redactors` and takes a list, not `redactor` taking one; and `secretRedactor` is a factory that has to be called. The required `destination` field was missing from the example entirely. They surfaced because a README is gated by nothing and `docs/` is compiled against the built SDK.
|
|
14
|
+
|
|
15
|
+
No API change.
|
|
16
|
+
|
|
17
|
+
## 30.0.0
|
|
18
|
+
|
|
19
|
+
### Major Changes
|
|
20
|
+
|
|
21
|
+
- e9a5e61: Remove the process-wide logger. A component given no logger now emits nothing instead of writing to your stderr.
|
|
22
|
+
|
|
23
|
+
**Removed from `@namzu/sdk`'s public surface:** `getRootLogger` and `configureLogger`. Both shipped `@deprecated` in an earlier minor, naming `installProcessSink` and `createLogger` as their replacements — this release is the removal that window existed for. `Logger` and `getLogCounters`, the other two exports from that module, are unchanged.
|
|
24
|
+
|
|
25
|
+
**What broke and what to do.**
|
|
26
|
+
|
|
27
|
+
`getRootLogger()` — build your own and pass it where you construct things:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { createLogger, installProcessSink, prettySink } from "@namzu/sdk";
|
|
31
|
+
|
|
32
|
+
installProcessSink(prettySink(process.stderr), "info");
|
|
33
|
+
const log = createLogger({
|
|
34
|
+
sink: prettySink(process.stderr),
|
|
35
|
+
level: { current: "info" },
|
|
36
|
+
resource: { "service.name": "my-app" },
|
|
37
|
+
scope: "my-app",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
await query({ ...params, runConfig: { ...runConfig, logger: log } });
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`configureLogger({ level })` — a level was only ever meaningful against a destination, and the destination is now yours. Pass the level to `installProcessSink(sink, level)`, or to `createLogger`'s `level` box, which stays live: assigning `level.current` retunes a logger already handed out.
|
|
44
|
+
|
|
45
|
+
Both take a level of type `LevelFilter` (`'debug' | 'info' | 'warn' | 'error' | 'silent'`), which is exported and unchanged.
|
|
46
|
+
|
|
47
|
+
**The behaviour change, which no type will catch.** `logger` was always optional on `RunConfig` and on every tool and component config, and omitting it used to mean "write to the process root" — in practice, your stderr, from a library, on a stream your program may be using for its own protocol. It now means `NOOP_LOGGER`: nothing is emitted, and the discard is counted, so `getLogCounters()` still tells you _N calls were thrown away_ rather than _nothing happened_. If your application relied on SDK diagnostics appearing without asking for them, they will stop appearing, and the compiler will not tell you. The field names are unchanged, so passing a logger is the whole migration.
|
|
48
|
+
|
|
49
|
+
Installing a process sink no longer reroutes SDK internals on its own. It sets the destination and owns the counter set; what routes through it is the logger you build over it and hand in.
|
|
50
|
+
|
|
51
|
+
**Also exported:** `getProcessSinkCounters()`, so a host that builds its own logger can count into the process's set rather than a private one — which is what keeps `getLogCounters()` and `namzu doctor`'s `logging.pipeline` check reporting real numbers.
|
|
52
|
+
|
|
3
53
|
## 29.0.0
|
|
4
54
|
|
|
5
55
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
type: Reference
|
|
3
3
|
title: "@namzu/sdk"
|
|
4
4
|
description: >-
|
|
5
|
-
|
|
6
|
-
an identity, a budget, a permission boundary
|
|
7
|
-
|
|
8
|
-
tags: [readme, package, sdk, kernel
|
|
5
|
+
An agent kernel for TypeScript. Runs an agent as a supervised unit of work
|
|
6
|
+
with an identity, a budget, a permission boundary and a durable record.
|
|
7
|
+
Renders no UI, hosts no service, and has no preferred model vendor.
|
|
8
|
+
tags: [readme, package, sdk, agent-kernel]
|
|
9
9
|
timestamp: 2026-08-17T00:00:00Z
|
|
10
10
|
status: active
|
|
11
11
|
diataxis: reference
|
|
@@ -15,338 +15,28 @@ diataxis: reference
|
|
|
15
15
|
|
|
16
16
|
<h1>@namzu/sdk</h1>
|
|
17
17
|
|
|
18
|
-
**
|
|
18
|
+
**An agent kernel for TypeScript.**
|
|
19
19
|
|
|
20
|
-
[](https://www.typescriptlang.org/)
|
|
24
|
-
[](https://nodejs.org/)
|
|
20
|
+
[](https://www.npmjs.com/package/@namzu/sdk)
|
|
21
|
+
[](https://github.com/cogitave/namzu/actions/workflows/ci.yml)
|
|
22
|
+
[](https://github.com/cogitave/namzu/blob/main/LICENSE.md)
|
|
25
23
|
|
|
26
|
-
[
|
|
24
|
+
[Install](#install) · [Quick start](#quick-start) · [What you get](#what-you-get) · [Documentation](#documentation)
|
|
27
25
|
|
|
28
26
|
</div>
|
|
29
27
|
|
|
30
28
|
---
|
|
31
29
|
|
|
32
|
-
|
|
30
|
+
An agent that works in a demo is a loop around a model call. An agent that
|
|
31
|
+
works in production is that loop plus everything around it — a budget that
|
|
32
|
+
stops it, an identity that attributes it, a boundary it cannot talk its way
|
|
33
|
+
past, a record that survives the process, and a way to shrink a conversation
|
|
34
|
+
that is about to overflow without corrupting it.
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
**Namzu is the kernel.** It runs agents the way an operating system runs processes. It does not render UI, it does not pick your database, it does not favor one LLM vendor. It gives you a surface — typed, versioned, documented — that any UI, any storage backend, and any model can plug into. The surface is small and stable; the guts underneath are deep.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## What Namzu Is
|
|
43
|
-
|
|
44
|
-
Namzu is a single-process TypeScript kernel with the following responsibilities:
|
|
45
|
-
|
|
46
|
-
- **Process execution and isolation.** Tools run outside the host process, under OS-level containment whose enforced controls vary by tier — and the kernel states per tier which of filesystem, network and process isolation it actually enforces, refusing to start a run whose required control the host cannot supply rather than silently downgrading it. No container runtime, no daemon, no sidecar. See [The Boundary](#1-the-boundary-sandbox-sandbox) for the table.
|
|
47
|
-
- **Agent lifecycle.** Parent/child agent spawn with depth tracking, budget splitting, and causal trace linkage. A supervisor can fork a subtree of agents and get their results back, with each child isolated from its siblings.
|
|
48
|
-
- **Scheduling.** Per-run token, cost, wall-clock, and iteration budgets. Limit checker, task router (cheap model for compaction, expensive for coding), tool tiering (LLM learns to prefer cheaper tools first).
|
|
49
|
-
- **Signals.** `AbortController` tree spanning parent and children. `cancel(taskId)` and `cancelAll(parentRunId)` propagate. Runs can be paused and resumed, aborted cleanly, and emit lifecycle events for every transition.
|
|
50
|
-
- **Memory management.** Working memory via structured compaction to a typed `WorkingState`. Long-term memory via an indexed, tag/query/status-searchable store with disk persistence. No vector database required by default.
|
|
51
|
-
- **Durability.** Atomic per-iteration checkpoints, an opt-in emergency core-dump on SIGINT/SIGTERM (`emergencySave: true` — a library must not seize a host process termination path by default), separate storage for runs, threads, conversations, activities, memories, and tasks.
|
|
52
|
-
- **IPC.** Native A2A (agent-to-agent) and MCP (Model Context Protocol) — both client and server, one SDK. An internal event bus with circuit breakers, file lock manager, and edit ownership tracking so concurrent agents do not stomp on each other.
|
|
53
|
-
- **Capability system.** Tools are first-class, typed, permissioned, and progressively disclosed. The LLM does not see the full tool catalog; tools start deferred, get activated on demand, and can be suspended. Each tool declares `readOnly`, `destructive`, `concurrencySafe`, `permissions`, `category`.
|
|
54
|
-
- **Syscall filtering.** Every tool call goes through a verification gate — allow / deny / ask, with built-in rules for read-only allowlist and dangerous pattern deny-list, plus custom regex rules. This is separate from sandbox isolation; it is the decision layer, the sandbox is the enforcement layer.
|
|
55
|
-
- **Retrieval-augmented context (RAG).** A full pipeline: chunking, embedding providers, ingestion, knowledge base storage, vector store, retriever, context assembler, and a first-class `rag-tool`.
|
|
56
|
-
- **Skills.** Disclosure-tiered capability bundles that the agent can load on demand, distinct from tools.
|
|
57
|
-
- **Personas.** YAML-defined identity, expertise, reflexes, and output format with inheritance — specialize a base persona by merging a single field, no prompt concatenation.
|
|
58
|
-
- **Advisory system.** Mid-execution consultation with specialized advisors. Provider-agnostic: put a security advisor on Bedrock, an architecture advisor on OpenRouter, and let the main agent decide when to consult whom.
|
|
59
|
-
- **Human-in-the-loop.** Structured plan review, per-tool approval with destructiveness flags, typed decision contracts, checkpoint/resume across sessions.
|
|
60
|
-
- **Plugin system.** Lifecycle-hooked plugin loader with MCP contributions, tool contributions, and manifest-driven resolution.
|
|
61
|
-
- **Multi-tenant isolation from day one.** Connector registries, vaults, config, and stores are tenant-scoped. Two organizations can share a process without cross-contamination.
|
|
62
|
-
- **Provider abstraction.** Seven drivers ship today, each its own package installed only if you use it, plus a scriptable mock pre-registered in the kernel. The `LLMProvider` interface is narrow enough that adding another is an afternoon. BYOK everywhere, no hidden hot paths for any vendor.
|
|
63
|
-
- **Telemetry.** OpenTelemetry-native spans and metrics. Cost accounting (input tokens, output tokens, cached tokens, cache write tokens, cache discount) flows from the provider into per-run, per-tenant rollups.
|
|
64
|
-
- **Prompt cache integration.** Hash-based system-prompt cache per thread, integrated with provider cache controls (OpenRouter `cacheControl` today, more planned), plus full cache telemetry in every run.
|
|
65
|
-
- **Vault.** BYOK credentials and secrets, tenant-scoped, pluggable backend.
|
|
66
|
-
- **Thread / Run separation.** Conversations (thread: user ↔ assistant messages across sessions) are cleanly separated from runs (tool calls, iterations, internal state). Multi-turn dialogs carry only the context that matters.
|
|
67
|
-
|
|
68
|
-
Every one of those bullets points at code that exists today in `src/`. The architecture is deep even where the surface is quiet.
|
|
69
|
-
|
|
70
|
-
## What Namzu Is Not
|
|
71
|
-
|
|
72
|
-
Equally important for scoping expectations:
|
|
73
|
-
|
|
74
|
-
- **Not a chat SDK.** No front-end framework bindings, no generative UI components, no ready-made chat hook. Your UI framework is your choice; the kernel hands you a typed event stream.
|
|
75
|
-
- **Not a hosted service.** There is no dashboard, no Namzu Cloud, no billing page. You run it in your own process.
|
|
76
|
-
- **Not a deployment adapter.** No web-framework or edge-runtime plumbing in the kernel. That belongs in separate packages or your own infra code.
|
|
77
|
-
- **Not a dev studio.** No bundled playground UI. A playground that consumes the kernel's event protocol could exist as a separate tool; it would not live inside `@namzu/sdk`.
|
|
78
|
-
- **Not a vector database.** RAG ships with a pluggable `VectorStore` interface; the kernel embeds no vector engine of its own. Bring your own.
|
|
79
|
-
- **Not an LLM router service.** Task routing is an in-process policy, not a hosted service.
|
|
80
|
-
- **Not a prompt management UI.** Personas are code-defined (YAML files in your repo), not database rows behind a web form.
|
|
81
|
-
|
|
82
|
-
The goal of that list is not to be minimal — the kernel is plenty rich. The goal is to keep the kernel's **interface surface** small and stable so the layers above can move fast without breaking what is underneath.
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## What the Kernel Provides
|
|
87
|
-
|
|
88
|
-
Category by category, with the symbol that implements it. This list
|
|
89
|
-
exists to be checked against the source, not against anybody else.
|
|
90
|
-
|
|
91
|
-
| Capability | What it is here |
|
|
92
|
-
|---|---|
|
|
93
|
-
| Process sandbox (OS-level) | Seatbelt profiles or mount + PID namespaces, refusing when a requested control cannot be enforced |
|
|
94
|
-
| Multi-tenancy | Tenant, project, thread and run are separate identities from day one, not a field added later |
|
|
95
|
-
| Sub-agent spawn | Parent/child with depth, budget and a shared pool the parent debits |
|
|
96
|
-
| Signal propagation | One abort tree; cancelling a parent tears down every descendant |
|
|
97
|
-
| Checkpoint and resume | Per iteration, versioned, written atomically, with the trace context to rejoin |
|
|
98
|
-
| Emergency save | Opt-in snapshot on a fatal signal, replayable through the ordinary restore path |
|
|
99
|
-
| Resource quotas | Token, cost and wall-clock caps per run and per child |
|
|
100
|
-
| Prompt cache | Cache anchors placed by the runtime and reported in telemetry |
|
|
101
|
-
| Thread ↔ Run separation | A conversation outlives the runs inside it |
|
|
102
|
-
| Agent-to-agent protocol | Client and server, in the kernel |
|
|
103
|
-
| Model Context Protocol | Client and server, in the kernel |
|
|
104
|
-
| Retrieval | A full pipeline in the kernel rather than an integration |
|
|
105
|
-
| Persona inheritance | Merge-based, declared in YAML |
|
|
106
|
-
| Advisory | Multiple advisors, each on whichever provider suits it |
|
|
107
|
-
| Context compaction | Structured working state, safe trim points, pinned messages |
|
|
108
|
-
| Tool tiering | Cost-aware, author-defined |
|
|
109
|
-
| Task routing | Per-task model with fallback chains |
|
|
110
|
-
| Progressive tool disclosure | Deferred, active and suspended tool states |
|
|
111
|
-
| Tool-call verification | Allow, deny or ask, with custom gates |
|
|
112
|
-
| File ownership | Edit locking so two concurrent writes cannot clobber |
|
|
113
|
-
| Circuit breakers | On the internal bus |
|
|
114
|
-
| Skills | Disclosure-tiered, separate from tools |
|
|
115
|
-
| Plugins | Install, enable, disable, with a hook lifecycle |
|
|
116
|
-
| Vault / BYOK | Tenant-scoped |
|
|
117
|
-
| Telemetry | OpenTelemetry natively, with GenAI conventions |
|
|
118
|
-
| Provider lock-in | None; the driver is a config choice |
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
## Architecture in Depth — Every Subsystem
|
|
123
|
-
|
|
124
|
-
Every folder under `src/` maps to a traditional OS concept. This section walks them one by one, in the order a request actually flows.
|
|
125
|
-
|
|
126
|
-
### 1. The Boundary: Sandbox (`sandbox/`)
|
|
127
|
-
|
|
128
|
-
Tools do not execute in the host process. What that buys you **depends on the tier the host can supply, and the tiers do not all enforce the same controls** — so the kernel keeps an honest table rather than a promise (`sandbox/isolation.ts`):
|
|
129
|
-
|
|
130
|
-
| Environment | Filesystem | Network | Process |
|
|
131
|
-
|---|---|---|---|
|
|
132
|
-
| `macos-seatbelt` | yes | yes | yes |
|
|
133
|
-
| `linux-namespace` | **no** | yes | yes |
|
|
134
|
-
| `basic` | no | no | no |
|
|
135
|
-
|
|
136
|
-
`linux-namespace` reports `filesystem: false` deliberately. It unshares the mount namespace but never remounts anything, so the child still sees the whole host filesystem — a private mount table is not confinement, and saying otherwise here would be the exact defect the table exists to prevent.
|
|
137
|
-
|
|
138
|
-
This matters because the failure it guards against is silent. If a run requires a control the host cannot enforce, `assertIsolation` **refuses to start it** rather than proceeding at a weaker tier: a security control that is accepted and then quietly not applied is worse than one that was never offered, because the caller stops looking. Use `isolationOf`, `missingIsolation` and `describeIsolation` to ask what you are actually getting before you rely on it.
|
|
139
|
-
|
|
140
|
-
The `SandboxProvider` abstraction (`sandbox/factory.ts`, `sandbox/provider/`) lets you supply a stronger provider without touching the rest of the kernel. The kernel enforces memory, timeout, and max-process limits on top of whatever the sandbox gives you.
|
|
141
|
-
|
|
142
|
-
### 2. Interprocess Communication: Bridge (`bridge/`) and Bus (`bus/`)
|
|
143
|
-
|
|
144
|
-
Two layers here, with different jobs.
|
|
145
|
-
|
|
146
|
-
**Bridge** is cross-process and cross-agent communication. The `bridge/a2a/` folder speaks the Agent-to-Agent protocol: your agents can publish agent cards describing their capabilities and can discover and invoke other agents' capabilities. The `bridge/mcp/` folder speaks the Model Context Protocol, both as a client (consume MCP servers as tools) and as a server (expose your Namzu tools to any MCP-speaking agent). The `bridge/sse/` folder contains the event mapper that turns in-process events into Server-Sent Events for any consumer on the other side of HTTP. What a *connector* contributes to the tool system lives with the connector, under `connector/tools/`, not here — `bridge/` is protocol boundaries.
|
|
147
|
-
|
|
148
|
-
**Bus** is in-process. This is where the kernel's internal nervous system lives. The bus emits typed `AgentBusEvent`s for every meaningful transition: run started, iteration begun, checkpoint created, tool call dispatched, tool result returned, agent paused, agent canceled, plan requested, plan approved, error thrown. On top of raw event fan-out, the bus offers three kernel-grade primitives:
|
|
149
|
-
|
|
150
|
-
- **`CircuitBreaker`** (`bus/breaker.ts`) closes the bus to a flapping agent. If an agent's run keeps failing, the breaker trips and prevents retry storms. Configurable failure threshold and reset timeout.
|
|
151
|
-
- **`FileLockManager`** (`bus/lock.ts`) holds locks on files across concurrent agents. A child cannot acquire a lock its parent or sibling already holds. Acquisition timeout is enforced.
|
|
152
|
-
- **`EditOwnershipTracker`** (`bus/ownership.ts`) records which run last claimed ownership of a path, emits events on contention, and lets a HITL layer decide who wins. When two agents try to edit the same file, one of them is told to wait or re-plan.
|
|
153
|
-
|
|
154
|
-
These exist because the moment you have more than one agent running in parallel against a shared filesystem, you need the kernel to arbitrate. Most frameworks either do not have parallelism or leave it to user space; Namzu treats it as a first-class kernel concern.
|
|
155
|
-
|
|
156
|
-
### 3. Process Lifecycle: Manager (`manager/`)
|
|
157
|
-
|
|
158
|
-
`manager/agent/lifecycle.ts` is the `fork()` + `exec()` + `waitpid()` of the kernel. When a parent agent (say a `SupervisorAgent`) spawns a child, the lifecycle manager:
|
|
159
|
-
|
|
160
|
-
- Allocates a slice of the parent's token budget, timeout budget, and cost budget to the child
|
|
161
|
-
- Creates a child `AbortController` linked to the parent's
|
|
162
|
-
- Builds a child config via the agent definition's `configBuilder(factoryOptions)`
|
|
163
|
-
- Stamps the child with `parentAgentId`, `parentRunId`, `threadId`, and `depth`
|
|
164
|
-
- Registers the child task in an internal `TaskRegistry` keyed by `TaskId`
|
|
165
|
-
- Emits `agent_pending` on the bus with parent/child/depth metadata
|
|
166
|
-
- Forwards every child event to the parent's run listener so the supervisor sees what its subtree is doing
|
|
167
|
-
|
|
168
|
-
When the parent is cancelled — by HITL, by a limit breach, or by an external signal — `cancelAll(parentRunId)` walks the subtree and aborts every descendant. This is the equivalent of signalling a whole process group.
|
|
169
|
-
|
|
170
|
-
`manager/connector/` manages the lifecycle of external connectors (MCP servers, HTTP connectors). `manager/plan/lifecycle.ts` coordinates HITL plan review. `manager/run/persistence.ts` is the run-level persistence surface, and `manager/run/emergency.ts` is the emergency-save subsystem (see §9 below).
|
|
171
|
-
|
|
172
|
-
### 4. Scheduling: Router (`model-router/`), Execution (`execution/`), Limit Checker (`run/LimitChecker.ts`)
|
|
173
|
-
|
|
174
|
-
The router policy (`model-router/task-router.ts`) decides which model a task should go to. Compaction and summarization go to cheap models; coding and complex reasoning stay on expensive ones. Tiering is user-defined — you decide which models belong in which tier and what guidance the LLM gets about preferring tier-1 tools first.
|
|
175
|
-
|
|
176
|
-
The execution layer (`execution/base.ts`, `execution/local.ts`) is the concrete executor that invokes the provider, dispatches tool calls, and produces iteration results. Execution is pluggable; you could swap in a remote executor without touching the agent patterns above.
|
|
177
|
-
|
|
178
|
-
The limit checker (`run/LimitChecker.ts`) is the kernel scheduler's enforcement point. Every iteration it checks: have we exceeded the token budget? The cost budget? The wall-clock timeout? The iteration count? Has the user issued an abort? If any is true, it returns a typed hard-stop decision — `cancelled`, `token_budget_exceeded`, `timeout`, `max_iterations` — and the run ends cleanly with a stop reason recorded in its metadata.
|
|
179
|
-
|
|
180
|
-
### 5. The Runtime Query Path (`runtime/`)
|
|
181
|
-
|
|
182
|
-
`runtime/query/` is where one iteration of the agent loop actually happens. The pieces:
|
|
183
|
-
|
|
184
|
-
- `runtime/query/context.ts` assembles the request context: system prompt, persona, skills, tools, messages.
|
|
185
|
-
- `runtime/query/context-cache.ts` implements `ContextCache` — a hash-based system-prompt cache per thread. If the prompt inputs have not changed since last iteration, the cache returns the same text so provider-level prompt caching can hit.
|
|
186
|
-
- `runtime/query/prompt.ts` owns `PromptBuilder` — structured, segment-based prompt assembly (static segment vs dynamic segment) that plays well with provider prompt caches.
|
|
187
|
-
- `runtime/query/guard.ts` runs pre-dispatch guards on the request.
|
|
188
|
-
- `runtime/query/executor.ts` actually calls the provider and streams the result.
|
|
189
|
-
- `runtime/query/result.ts` normalizes the provider's response into the kernel's canonical shape.
|
|
190
|
-
- `runtime/query/checkpoint.ts` writes the iteration's checkpoint.
|
|
191
|
-
- `runtime/query/tooling.ts` bridges the iteration to the tool system, including progressive disclosure state.
|
|
192
|
-
- `runtime/query/iteration/` contains the iteration machinery.
|
|
193
|
-
- `runtime/query/plugin-hooks.ts` lets plugins observe and shape iterations.
|
|
194
|
-
- `runtime/query/events.ts` emits the typed events that feed the bus.
|
|
195
|
-
|
|
196
|
-
`runtime/decision/` (with `parser.ts` and `fallback.ts`) parses LLM decisions (tool calls vs final answer vs thinking vs advisory request) and falls back gracefully when the LLM returns malformed output.
|
|
197
|
-
|
|
198
|
-
### 6. Memory Management: Compaction (`compaction/`) and Store (`store/`)
|
|
199
|
-
|
|
200
|
-
Memory in the kernel is two systems cooperating.
|
|
201
|
-
|
|
202
|
-
**Working memory** is `compaction/`. When a thread's context approaches the model's window, the kernel does not truncate. It runs the `structured` compaction manager (default in `compaction/managers/structured.ts`, with `slidingWindow.ts` and `null.ts` as alternatives), which incrementally extracts `task / plan / files / decisions / failures` from the message stream into a typed `WorkingState`. The extractor (`compaction/extractor.ts`), verifier (`compaction/verifier.ts`), and serializer (`compaction/serializer.ts`) together produce compact markdown that replaces old messages. The agent keeps context awareness at a fraction of the token cost. `compaction/dangling.ts` handles partial tool-call streams that could otherwise corrupt the conversation state.
|
|
203
|
-
|
|
204
|
-
**Long-term memory** is `store/memory/`. The `MemoryIndex` (with `InMemoryMemoryIndex` as the default and a disk-backed variant) stores typed `MemoryIndexEntry` records, searchable by free-text query, tag set, and status filter. It persists to disk atomically. There is no required vector database — the default is good-old tag and text search. You can layer an embedding-backed index on top if you want, but the kernel does not assume it.
|
|
205
|
-
|
|
206
|
-
Alongside memory, `store/` has sibling stores for every kernel concept: `store/run/` (runs, iterations, checkpoints), `store/conversation/` (threads and messages), `store/activity/` (activity log), `store/task/` (task registry), and an in-memory generic `InMemoryStore` for tests and ephemeral workloads.
|
|
207
|
-
|
|
208
|
-
### 7. The Capability System: Tools (`tools/`) and Registry (`registry/`)
|
|
209
|
-
|
|
210
|
-
Tools in Namzu are first-class typed values, not JSON schemas you have to keep in sync with a handler somewhere else. `defineTool()` takes a Zod `inputSchema`, a Zod `outputSchema` (optional), and an `execute` function. It also takes **declarations** the kernel uses for routing and safety:
|
|
211
|
-
|
|
212
|
-
- `category` — e.g. `network`, `filesystem`, `compute`, `memory`.
|
|
213
|
-
- `permissions` — e.g. `network_access`, `write_filesystem`. Enforced at dispatch time.
|
|
214
|
-
- `readOnly` — predicate over input; tools that only read get different treatment by the verification gate and tool tiering.
|
|
215
|
-
- `destructive` — boolean flag that triggers HITL approval when true.
|
|
216
|
-
- `concurrencySafe` — whether two concurrent runs can invoke this tool with no interference.
|
|
217
|
-
|
|
218
|
-
`tools/builtins/` ships file I/O, shell, and glob-search tools. `tools/advisory/`, `tools/memory/`, `tools/task/`, and `tools/coordinator/` ship kernel-facing tools that let agents consult advisors, query memory, coordinate siblings, and manage their task registry from inside the agent loop.
|
|
219
|
-
|
|
220
|
-
**Progressive disclosure** is unique to Namzu. Tools exist in three states — `deferred`, `activated`, `suspended`. The LLM does not see the full tool catalog; it sees the current active set plus a searchable summary of deferred tools. When it needs something specific, it activates it; when it is done, it suspends it. This keeps the context window focused, reduces hallucinated tool calls, and lets a single agent work across dozens of tools without drowning in a prompt.
|
|
221
|
-
|
|
222
|
-
**Tool tiering** teaches the LLM a cost hierarchy. You define tiers ("tier-1: local", "tier-2: fast remote", "tier-3: expensive API"), each with its own guidance template, and the kernel instructs the LLM to prefer lower tiers first. Unlike hardcoded approaches, every label, priority, and template is yours.
|
|
223
|
-
|
|
224
|
-
Registries (`registry/`) are the kernel's object tables. `registry/tool/` is the canonical tool catalog. `registry/agent/` holds agent definitions (the thing you can `AgentManager.spawn()`). `registry/connector/` holds connector catalogs. `registry/plugin/` holds plugins. `ManagedRegistry` is the shared base class with tenant scoping.
|
|
225
|
-
|
|
226
|
-
### 8. The Decision Layer: Verification Gate (`verification/`)
|
|
227
|
-
|
|
228
|
-
Before any tool call leaves the kernel, it goes through `verification/gate.ts`'s `VerificationGate`. Think of it as the kernel's seccomp — a rule-based decision layer that says *allow*, *deny*, or *ask*.
|
|
229
|
-
|
|
230
|
-
Built-in rules:
|
|
231
|
-
|
|
232
|
-
- **`allow_read_only`** — if the tool's `readOnly(input)` returns true, allow.
|
|
233
|
-
- **`deny_dangerous_patterns`** — if the input matches any pattern from `DANGEROUS_PATTERNS` (shell injection, common exfiltration signatures, etc.), deny.
|
|
234
|
-
- **Custom regex rules** — per-tenant, per-agent, or global.
|
|
235
|
-
|
|
236
|
-
The `ask` decision hands control to the HITL layer. The verification gate is the kernel layer that makes "destructive tool requires approval" a policy, not a user-space convention.
|
|
237
|
-
|
|
238
|
-
Verification is intentionally separate from the sandbox: verification is the *decision*, sandbox is the *enforcement*. If a rule fails to deny and a call somehow gets through, the sandbox is still there to contain the damage. Defense in depth, kernel-style.
|
|
239
|
-
|
|
240
|
-
### 9. Durability: Checkpoints and Emergency Save
|
|
241
|
-
|
|
242
|
-
The kernel assumes processes crash. Two layers make sure that when they do, you do not lose the run.
|
|
243
|
-
|
|
244
|
-
**Checkpoints** (`store/run/disk.ts`) are atomic per-iteration snapshots. Each `IterationCheckpoint` captures the run state at a super-step boundary — messages, working state, tool-call state, usage, cost, iteration index. Writes are atomic via write-temp-rename (Convention #8). You can read them, list them, and delete them. A future `Run.replay(runId, { fromCheckpoint })` API will build on top of this; the storage is already there.
|
|
245
|
-
|
|
246
|
-
**Emergency save** (`manager/run/emergency.ts`) is the kernel's core-dump. Pass `emergencySave: true` to `query()` and `EmergencySaveManager` installs handlers for SIGINT, SIGTERM and `uncaughtException`; when the process is dying the run's `toEmergencySnapshot()` is flushed atomically to an `emergency/` directory, and `replay({ fromCheckpoint: 'emergency' })` reads it back. The handlers are removed when the run settles.
|
|
247
|
-
|
|
248
|
-
It is **opt-in on purpose.** Attaching means calling `process.on(...)` with handlers that `process.exit()` — a library must not seize a host's termination path by default, and the manager is a singleton, so with concurrent runs the last one to attach would silently become the only one saved. Turn it on for a process that owns its run end to end (a CLI, a single-run worker); leave it off inside a server that has its own drain sequence.
|
|
249
|
-
|
|
250
|
-
Together these give Namzu durable execution without requiring a database. Runs resume across crashes, across reboots, across graceful shutdowns.
|
|
251
|
-
|
|
252
|
-
### 10. Retrieval-Augmented Generation: RAG (`rag/`)
|
|
253
|
-
|
|
254
|
-
RAG is a full kernel subsystem, not a bolt-on. The pipeline:
|
|
255
|
-
|
|
256
|
-
- `rag/chunking.ts` — text chunking strategies (configurable by `ChunkingConfig`).
|
|
257
|
-
- `rag/embedding.ts` — the `EmbeddingProvider` abstraction. Providers are BYOK and swappable.
|
|
258
|
-
- `rag/ingestion.ts` — end-to-end ingest: document → chunks → embeddings → vector store.
|
|
259
|
-
- `rag/vector-store.ts` — the `VectorStore` interface, tenant-scoped via `TenantId`. Bring your own backend (pgvector, Pinecone, an in-memory impl for tests).
|
|
260
|
-
- `rag/knowledge-base.ts` — a named collection of documents with metadata and config.
|
|
261
|
-
- `rag/retriever.ts` — the retrieval query path: vector, keyword (BM25) or hybrid, with configurable top-k and score threshold. Hybrid normalises both rankings before blending them by `hybridAlpha`. **There is no rerank stage.** This line used to promise one; there was no rerank stage behind it and no setting to turn it on, so a reader could configure for it and receive nothing.
|
|
262
|
-
- `rag/context-assembler.ts` — turns retrieval hits into prompt-ready context windows.
|
|
263
|
-
- `rag/rag-tool.ts` — a first-class tool your agent can invoke, not an external integration.
|
|
264
|
-
|
|
265
|
-
RAG lives in the kernel because retrieval is a capability every non-trivial agent needs. Making you wire it up from plugins every time was not the right default.
|
|
266
|
-
|
|
267
|
-
### 11. Skills (`skills/`)
|
|
268
|
-
|
|
269
|
-
Skills are disclosure-tiered capability bundles distinct from tools. A skill is a named body of knowledge, workflow, or policy that the agent can load on demand. `skills/loader.ts` reads them from disk; `skills/registry.ts` holds the active catalog; each skill has a `SkillDisclosureLevel` that decides when the LLM sees it (always visible, searchable-on-demand, explicit-activation-only). Skills and tools together form the two axes of an agent's capability surface.
|
|
270
|
-
|
|
271
|
-
### 12. Personas (`persona/`)
|
|
272
|
-
|
|
273
|
-
Personas describe who an agent is. `persona/assembler.ts` loads them from YAML and composes them with inheritance: a base `researcher` persona defines identity, expertise areas, output format, and reflexes; an `ml-researcher` child merges a single field (`expertise: [...base, 'ML', 'PyTorch']`) and inherits everything else. The assembler produces a typed `AgentPersona` that flows into the prompt as a structured segment (not a string concatenation, not a template hack), so prompt-cache-friendliness is preserved.
|
|
274
|
-
|
|
275
|
-
Personas are code-defined (YAML files in your repo). There is no database, no admin UI, no runtime mutation. That is deliberate: your agent's identity belongs in version control.
|
|
276
|
-
|
|
277
|
-
### 13. Advisory System (`advisory/`)
|
|
278
|
-
|
|
279
|
-
An advisor is a specialized assistant a running agent can consult mid-execution. The main agent is solving a task; halfway through it hits a decision it is not confident about, or a domain it wants a second opinion on. It fires an advisory request with context; the advisory layer evaluates triggers, routes to the right advisor, executes on a (possibly different) provider, and returns a structured answer the main agent can act on.
|
|
280
|
-
|
|
281
|
-
Pieces:
|
|
282
|
-
|
|
283
|
-
- `advisory/registry.ts` — `AdvisorRegistry`, the catalog of available advisors keyed by domain.
|
|
284
|
-
- `advisory/evaluator.ts` — `TriggerEvaluator`, decides whether an advisory should fire given context and config.
|
|
285
|
-
- `advisory/executor.ts` — `AdvisoryExecutor`, runs the advisor, collects its output, and feeds it back.
|
|
286
|
-
- `advisory/context.ts` — `AdvisoryContext`, the payload passed to advisors.
|
|
287
|
-
|
|
288
|
-
Advisors are **provider-agnostic** and there can be many: put a security advisor on one provider, an architecture advisor on another, a legal advisor on a third, and let the agent decide who to consult. A single advisor pinned to one vendor cannot express "ask the model that is actually good at this".
|
|
289
|
-
|
|
290
|
-
### 14. Human-in-the-Loop (`types/hitl/`, `manager/plan/lifecycle.ts`, `types/decision/`)
|
|
291
|
-
|
|
292
|
-
HITL is structured, not just a "pause and wait for input" hook. The kernel defines typed decision contracts: the LLM produces a plan, the plan can be approved / edited / rejected, approval can be per-tool with explicit destructiveness acknowledgment, rejection can carry feedback that re-enters the loop as a new iteration. The plan lifecycle has its own manager so that pending plans persist across checkpoint resumes. The verification gate's `ask` decision routes into this same HITL layer.
|
|
293
|
-
|
|
294
|
-
The kernel does not render a UI for this — it emits events and exposes a typed API so the UI layer you choose can render them however you like.
|
|
295
|
-
|
|
296
|
-
### 15. Providers (`provider/`)
|
|
297
|
-
|
|
298
|
-
An LLM provider implements a narrow interface: given a typed request, return a typed response (streaming or not) and propagate normalized usage, cost, and cache telemetry. Concrete providers live in dedicated sibling packages — `@namzu/anthropic`, `@namzu/bedrock`, `@namzu/http`, `@namzu/lmstudio`, `@namzu/ollama`, `@namzu/openai`, `@namzu/openrouter` — each calling `ProviderRegistry.register('<vendor>', Class, capabilities)` via a `register<Vendor>()` helper. The kernel itself ships only the `LLMProvider` interface, the `ProviderRegistry`, and a pre-registered `MockLLMProvider` for tests and offline work. `provider/telemetry/` normalizes provider-specific response fields (`cache_read_input_tokens`, `cache_creation_input_tokens`, `cache_discount`, Bedrock equivalents) into a single kernel-wide telemetry shape.
|
|
299
|
-
|
|
300
|
-
`ProviderRegistry` is the single entry point. `ProviderRegistry.create({ type, ... })` returns `{ provider, capabilities }`; TypeScript module augmentation from each provider package gives type-narrowed config. Providers are stateless enough to be shared across runs.
|
|
301
|
-
|
|
302
|
-
### 16. Connectors (`connector/`)
|
|
303
|
-
|
|
304
|
-
A connector is how an agent reaches external systems. `connector/BaseConnector.ts` is the abstract base; `connector/mcp/` implements MCP connectors in both `stdio` and `http` transports with a `client.ts` and an `adapter.ts` that turns MCP tools into Namzu `ToolDefinition`s; `connector/builtins/` ships the built-in connectors (HTTP, shell, etc.). WHERE a call runs is not a connector concern and does not live here: all five execution backends are in `execution/`, and a connector is one caller of one. Plugin contributions can register connectors at runtime.
|
|
305
|
-
|
|
306
|
-
### 17. Prompt Cache Integration
|
|
307
|
-
|
|
308
|
-
The kernel takes prompt caching seriously because token cost is the number-one production constraint for agents. `runtime/query/context-cache.ts` maintains a per-thread `ContextCache` that hashes the inputs (system prompt + persona + skills + tools + base prompt) and only rebuilds when the hash changes. When the provider supports cache controls (OpenRouter's `cacheControl` parameter today, Anthropic and Bedrock cache headers in progress), the kernel attaches them, and the response's cache telemetry (`cache_read_input_tokens`, `cache_creation_input_tokens`, `cache_discount`) flows back into the run's usage metrics.
|
|
309
|
-
|
|
310
|
-
This is why `PromptBuilder` splits a request into static and dynamic segments: the static segment is the cache target, and the kernel does the bookkeeping to keep it stable across iterations so the cache actually hits.
|
|
311
|
-
|
|
312
|
-
### 18. Vault (`vault/`)
|
|
313
|
-
|
|
314
|
-
The vault holds BYOK credentials and arbitrary secrets. `InMemoryCredentialVault` is the default backend; the `CredentialVault` interface lets you plug in your own. Credentials are tenant-scoped — tenant A cannot see tenant B's keys. Tools, providers, and connectors resolve credentials through the vault rather than reading environment variables directly, so you can rotate without redeploying and you can audit who accessed what.
|
|
315
|
-
|
|
316
|
-
### 19. Telemetry (`telemetry/`)
|
|
317
|
-
|
|
318
|
-
OpenTelemetry-native. `telemetry/attributes.ts` defines the canonical attribute keys; `telemetry/metrics.ts` defines the kernel's metrics surface. Every iteration, every tool call, every provider call emits spans with consistent attributes: `run.id`, `thread.id`, `agent.id`, `tenant.id`, `tool.name`, `provider.name`, `model`, `usage.input_tokens`, `usage.output_tokens`, `usage.cached_tokens`, `cost.usd`. Wire your existing OTel collector, or pipe to LangSmith / Langfuse / Braintrust via their OTel adapters.
|
|
319
|
-
|
|
320
|
-
### 20. Plugin System (`plugin/`)
|
|
321
|
-
|
|
322
|
-
Plugins extend the kernel at runtime. A plugin manifest declares what it contributes (tools, MCP servers, advisors, connectors), and the kernel's `plugin/loader.ts` reads manifests from disk, `plugin/resolver.ts` namespaces everything safely, and `plugin/lifecycle.ts` hooks plugin init / shutdown into the kernel's own lifecycle. Plugins can subscribe to iteration hooks via `runtime/query/plugin-hooks.ts` and shape what the LLM sees.
|
|
323
|
-
|
|
324
|
-
Plugins are how a community ecosystem grows around the kernel without the kernel having to ship batteries for every use case.
|
|
325
|
-
|
|
326
|
-
### 21. Gateway (`gateway/`)
|
|
327
|
-
|
|
328
|
-
`gateway/local.ts` is the local-process gateway — a thin translation layer between an external caller (HTTP, WebSocket, stdin, another agent over A2A) and the kernel's run API. Put a real HTTP server in front of it and you have an agent service; wrap it in a CLI and you have an agent shell. The gateway is where your application layer plugs into the kernel.
|
|
329
|
-
|
|
330
|
-
### 22. Agent Patterns (`agents/`)
|
|
331
|
-
|
|
332
|
-
Four patterns ship in the kernel. They are not mandatory — you can write your own `AbstractAgent` subclass for custom loops — but these are the shapes most real workloads want.
|
|
333
|
-
|
|
334
|
-
- **`ReactiveAgent`** — the canonical agent loop. Prompt → LLM → tool call(s) → iterate → stop. Handles token budget, cost limit, timeout, max iterations, HITL injection, progressive tool disclosure, compaction, and checkpointing automatically.
|
|
335
|
-
- **`PipelineAgent`** — deterministic sequential steps. Each step is a typed function; output of step N is input of step N+1. Rolls back on failure. Useful for ETL, RAG ingestion, multi-stage document processing.
|
|
336
|
-
- **`RouterAgent`** — an LLM classifies the input and delegates to the best-suited agent from a configured set of candidates, with a fallback. Useful for intent routing in customer support, dispatcher bots, and multi-expert systems.
|
|
337
|
-
- **`SupervisorAgent`** — a coordinator that spawns and orchestrates a set of specialized child agents. Tracks the full parent/child/depth hierarchy, aggregates results, handles partial failures, and honors the shared budget tracker.
|
|
338
|
-
|
|
339
|
-
All four sit on top of the same lifecycle manager, the same limit checker, the same bus, the same verification gate. Switching patterns does not change what safety or durability the kernel provides.
|
|
340
|
-
|
|
341
|
-
### 23. Multi-Tenant Isolation
|
|
342
|
-
|
|
343
|
-
Every registry, every store, every vault is tenant-scoped. `TenantId` is a branded ID threaded through the kernel's types. A run for tenant A cannot accidentally read tenant B's knowledge base, invoke tenant B's tools, or resolve tenant B's credentials. This is not a feature you turn on — it is the default, and a single-tenant setup is just a special case.
|
|
344
|
-
|
|
345
|
-
### 24. Thread / Run Separation
|
|
346
|
-
|
|
347
|
-
A **thread** is a conversation: a series of user ↔ assistant messages, possibly spanning many sessions, probably spanning many days. A **run** is a single execution pass: an input, iterations, tool calls, usage, cost, result. One thread has many runs. Most frameworks conflate the two; Namzu keeps them explicit, with separate stores, separate IDs, and separate serialization. Multi-turn dialogs carry only the context the kernel thinks matters (via compaction), and run traces stay auditable without drowning in prior-turn tool chatter.
|
|
348
|
-
|
|
349
|
-
---
|
|
36
|
+
This is those other things. It runs an agent the way an operating system runs
|
|
37
|
+
a process: given an identity and a budget, confined, scheduled, checkpointed,
|
|
38
|
+
and what it did is written down. It renders no UI, requires no database, hosts
|
|
39
|
+
no service, and has no preferred model vendor.
|
|
350
40
|
|
|
351
41
|
## Install
|
|
352
42
|
|
|
@@ -354,14 +44,22 @@ A **thread** is a conversation: a series of user ↔ assistant messages, possibl
|
|
|
354
44
|
pnpm add @namzu/sdk
|
|
355
45
|
```
|
|
356
46
|
|
|
357
|
-
|
|
47
|
+
Requires Node.js 20+, ESM, and TypeScript strict mode.
|
|
358
48
|
|
|
359
|
-
The
|
|
360
|
-
|
|
49
|
+
The kernel ships alone. Add a driver for whichever backend you use —
|
|
50
|
+
[`@namzu/anthropic`](https://www.npmjs.com/package/@namzu/anthropic),
|
|
51
|
+
[`@namzu/openai`](https://www.npmjs.com/package/@namzu/openai),
|
|
52
|
+
[`@namzu/bedrock`](https://www.npmjs.com/package/@namzu/bedrock),
|
|
53
|
+
[`@namzu/openrouter`](https://www.npmjs.com/package/@namzu/openrouter),
|
|
54
|
+
[`@namzu/ollama`](https://www.npmjs.com/package/@namzu/ollama),
|
|
55
|
+
[`@namzu/lmstudio`](https://www.npmjs.com/package/@namzu/lmstudio),
|
|
56
|
+
or the zero-dependency [`@namzu/http`](https://www.npmjs.com/package/@namzu/http).
|
|
57
|
+
With none of them the kernel still runs against `MockLLMProvider`, which is
|
|
58
|
+
pre-registered and scriptable.
|
|
361
59
|
|
|
362
|
-
## Quick
|
|
60
|
+
## Quick start
|
|
363
61
|
|
|
364
|
-
```
|
|
62
|
+
```ts
|
|
365
63
|
import { defineTool, ProviderRegistry, ReactiveAgent, ToolRegistry } from '@namzu/sdk'
|
|
366
64
|
import { registerOpenRouter } from '@namzu/openrouter'
|
|
367
65
|
import { z } from 'zod'
|
|
@@ -385,7 +83,7 @@ const searchWeb = defineTool({
|
|
|
385
83
|
|
|
386
84
|
const { provider } = ProviderRegistry.create({
|
|
387
85
|
type: 'openrouter',
|
|
388
|
-
apiKey: process.env.OPENROUTER_KEY
|
|
86
|
+
apiKey: process.env.OPENROUTER_KEY ?? '',
|
|
389
87
|
})
|
|
390
88
|
|
|
391
89
|
const tools = new ToolRegistry()
|
|
@@ -400,98 +98,38 @@ const agent = new ReactiveAgent({
|
|
|
400
98
|
})
|
|
401
99
|
|
|
402
100
|
const result = await agent.run(
|
|
403
|
-
{
|
|
101
|
+
{
|
|
102
|
+
messages: [{ role: 'user', content: 'Summarize the latest LLM benchmarks' }],
|
|
103
|
+
workingDirectory: process.cwd(),
|
|
104
|
+
},
|
|
404
105
|
{ model: 'anthropic/claude-sonnet-4', tokenBudget: 8192, timeoutMs: 600_000, provider, tools },
|
|
405
106
|
)
|
|
406
107
|
```
|
|
407
108
|
|
|
408
|
-
That is
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
## Design Principles
|
|
415
|
-
|
|
416
|
-
Five choices shape every decision in the kernel.
|
|
417
|
-
|
|
418
|
-
**No workarounds. Fix at the root.** When something is wrong, we fix the pattern, not the symptom. A subtle bug in the lifecycle manager means the lifecycle manager changes — we do not paper over it in the agent pattern that calls it.
|
|
419
|
-
|
|
420
|
-
**Type safety is the foundation.** Every resource ID is branded (`RunId`, `ThreadId`, `TaskId`, `TenantId`, `AgentId`, `ToolId`, `MemoryId`, `ChunkId`...). Every discriminated union has exhaustiveness checks. Every public API has Zod-validated inputs at the boundary. The TypeScript compiler is not a formality; it is the first line of defense.
|
|
421
|
-
|
|
422
|
-
**Deny by default. Fail fast.** Sandboxes deny file I/O by default. Verification gates deny tool calls by default unless a rule allows them. Limit checkers fail the run the moment a budget is breached. Configuration errors throw at boot, not at the 90-minute mark of a long-running job.
|
|
423
|
-
|
|
424
|
-
**Dependency direction is sacred.** `contracts` knows nothing about `sdk`. `sdk` knows nothing about `agents` or `api`. Circular dependencies are a compile error, not a code-review suggestion. This is what keeps the kernel's interface surface small even as its guts grow.
|
|
425
|
-
|
|
426
|
-
**Convention over surprise.** Every new feature follows a shared pattern language — Registries, Managers, Stores, Runs, Bridges, Providers. You read one subsystem, you can navigate the next one.
|
|
427
|
-
|
|
428
|
-
---
|
|
429
|
-
|
|
430
|
-
## The Agent Event Protocol (AEP)
|
|
431
|
-
|
|
432
|
-
The kernel's contract with the outside world is a typed, versioned event stream. Any UI, any shell, any observability tool subscribes to AEP and renders what it wants.
|
|
433
|
-
|
|
434
|
-
AEP flows over three transports:
|
|
435
|
-
|
|
436
|
-
- **Bus** (`bus/`) — in-process, for tightly-coupled consumers.
|
|
437
|
-
- **SSE** (`bridge/sse/mapper.ts`) — cross-process over HTTP, for web UIs and remote observers.
|
|
438
|
-
- **A2A** (`bridge/a2a/`) — cross-agent, for multi-agent meshes.
|
|
439
|
-
|
|
440
|
-
Every transport emits the same event shape. Event types include run lifecycle (`run_started`, `run_paused`, `run_completed`), iteration events (`iteration_started`, `checkpoint_created`), tool events (`tool_called`, `tool_result`), agent events (`agent_pending`, `agent_canceled`), plan events (`plan_requested`, `plan_approved`), advisory events, and error events. They carry consistent metadata: `runId`, `threadId`, `agentId`, `tenantId`, `timestamp`, `depth`, `parentRunId`.
|
|
441
|
-
|
|
442
|
-
AEP v1 is being finalized. Until the spec is stamped, treat the event shapes as semver-minor.
|
|
109
|
+
That run is sandbox-isolated, checkpointed and instrumented, with prompt
|
|
110
|
+
caching, progressive tool disclosure and structured compaction already wired
|
|
111
|
+
in. Those are not features you enable — they are how the kernel runs. Swap the
|
|
112
|
+
`registerOpenRouter()` line for any other driver and everything below it is
|
|
113
|
+
unchanged.
|
|
443
114
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
## What You Can Build
|
|
447
|
-
|
|
448
|
-
Namzu is not a toy. It is meant for real workloads.
|
|
449
|
-
|
|
450
|
-
**Personal and homelab.** A home-automation agent monitoring logs, restarting services, running health checks. A personal research agent feeding PDFs and notes through the RAG pipeline into a knowledge base, answering with citations from your own data. A code-review agent watching your repos, reviewing PRs with a `PipelineAgent` (extract diff → analyze → write review), and posting feedback automatically. A media organizer scanning your library, categorizing files, renaming based on metadata, deduplicating.
|
|
451
|
-
|
|
452
|
-
**Business and team.** A customer-support triage system where a `RouterAgent` classifies incoming tickets and delegates to specialized children (billing, technical, general), each with its own persona, tools, and knowledge base. A document-processing pipeline ingesting contracts, invoices, and reports through RAG, extracting key data, flagging anomalies, generating summaries, with HITL approval for anything destructive. An internal-ops bot that plugs into Slack, Jira, and your database over MCP. A compliance checker where a `SupervisorAgent` coordinates sub-agents each checking a different regulation, then aggregates results and routes flagged items through plan review.
|
|
453
|
-
|
|
454
|
-
**Platform and SaaS.** This is the shape Namzu was designed for from day one. Agent-as-a-Service — each customer gets isolated agents with their own BYOK keys, connector configs, and knowledge bases; tenant isolation is built in, not bolted on. An agent marketplace — agents are portable definitions (`info + tools + persona + skills`), publishable, deployable by any customer with their own keys, specializable through persona inheritance. Cross-organization workflows where agents from different companies discover each other via A2A agent cards and collaborate without a central authority.
|
|
455
|
-
|
|
456
|
-
---
|
|
457
|
-
|
|
458
|
-
## Quality Bar
|
|
459
|
-
|
|
460
|
-
The architectural bar this kernel holds itself to is written down in
|
|
461
|
-
its own terms: dependency direction is one-way and enforced, every
|
|
462
|
-
public type has a producer and a consumer, a control that cannot be
|
|
463
|
-
enforced is refused rather than downgraded, and a gate says which way
|
|
464
|
-
it fails. Those are checkable in the source, which is the only kind of
|
|
465
|
-
claim worth making.
|
|
115
|
+
## What you get
|
|
466
116
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
the surface: fewer names, better names, and a deprecation window on every one
|
|
476
|
-
that changes.
|
|
477
|
-
|
|
478
|
-
This section used to carry a version-numbered roadmap. It was written at 0.x
|
|
479
|
-
and the package is well past it — several of its items shipped under different
|
|
480
|
-
names, one of them (`ContextCache`) is now deprecated, and a plan a reader
|
|
481
|
-
cannot trust is worse than no plan. The changelog is the record of what
|
|
482
|
-
actually landed; the repository's issues are where what is next gets argued.
|
|
483
|
-
|
|
484
|
-
Explicitly out of scope, and staying that way: framework chat hooks, hosting
|
|
485
|
-
adapters, a studio playground, a dashboard. They belong on top of a kernel with
|
|
486
|
-
a small stable interface, which is the only reason that interface can stay
|
|
487
|
-
small.
|
|
488
|
-
|
|
489
|
-
---
|
|
117
|
+
| | |
|
|
118
|
+
|---|---|
|
|
119
|
+
| **Boundary** | tool calls run confined; a permission gate decides before, not after |
|
|
120
|
+
| **Budget** | tokens, money, wall clock and iterations, enforced rather than hoped for |
|
|
121
|
+
| **Identity** | tenant → project → thread → session → run, on every record and span |
|
|
122
|
+
| **Durability** | checkpoints a run resumes from, and a record that outlives the process |
|
|
123
|
+
| **Compaction** | a conversation about to overflow is shrunk without being corrupted |
|
|
124
|
+
| **Observability** | OpenTelemetry spans and metrics, and a log pipeline you own the sink for |
|
|
490
125
|
|
|
491
|
-
##
|
|
126
|
+
## Documentation
|
|
492
127
|
|
|
493
|
-
[
|
|
128
|
+
- [The kernel in depth](https://github.com/cogitave/namzu/blob/main/docs/sdk/architecture.md) — every subsystem, the design principles, the event protocol
|
|
129
|
+
- [An agent is a folder](https://github.com/cogitave/namzu/blob/main/docs/sdk/directory/agent-as-a-directory.md)
|
|
130
|
+
- [Tools and safety](https://github.com/cogitave/namzu/tree/main/docs/sdk/tools) · [Observability](https://github.com/cogitave/namzu/tree/main/docs/sdk/observability) · [Integrations](https://github.com/cogitave/namzu/tree/main/docs/sdk/integrations)
|
|
131
|
+
- [All docs](https://github.com/cogitave/namzu/tree/main/docs)
|
|
494
132
|
|
|
495
|
-
|
|
133
|
+
## License
|
|
496
134
|
|
|
497
|
-
|
|
135
|
+
FSL-1.1-MIT, converting to MIT two years after each release.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugin/loader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,0BAA0B,CAAA;AAEpF,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,oBAAoB,CAAA;AAE/D;;;GAGG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugin/loader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,cAAc,EAAwB,MAAM,0BAA0B,CAAA;AAEpF,OAAO,EAAE,KAAK,MAAM,EAAiB,MAAM,oBAAoB,CAAA;AAE/D;;;GAGG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA6CxF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOnF;AAuBD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IACjC;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAClC;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,GAAE,iBAAsB,GAAG,IAAI,CAkB7F;AAED,6GAA6G;AAC7G,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,CAAA;AAE5C;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACtC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;IAChC,yDAAyD;IACzD,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;IAC/C,wDAAwD;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,qBAAqB,CAC1C,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,sBAAsB,GAC9B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAgChD"}
|