English | 简体中文
Alembic Agent is the standalone runtime package for Alembic's agent orchestration: a single ReAct (Thought → Action → Observation) execution engine, an AI provider/transport stack covering five vendors, and a contract-first tool system — extracted from the Alembic product repository so hosts can embed it through dependency injection.
- TypeScript + ESM (NodeNext), Node >= 22, formatted/linted with Biome.
- Deterministic capabilities (ProjectContext, knowledge persistence, dimension
configs, logging) are not implemented here — they are consumed through
the
@alembic/corepackage entrypoints.
Is:
- Agent execution engine — one
AgentRuntimeReAct kernel plus Strategy orchestration, Policy constraints, Capability composition, and layered memory/context. - AI provider layer — a unified
AiProviderabstraction over OpenAI, Claude, Google Gemini, DeepSeek, and Ollama, with per-vendor transports, reliability control (retry / circuit breaker / concurrency / 429 cooldown), parameter guarding, and structured-output repair. - Tool system — a single-source tool registry +
ToolRouter+ kernel contracts, with built-incode/terminal/knowledge/graph/memory/metahandlers, a terminal safety model, and output compression.
Is not:
- Not the Core deterministic kernel (lives in
@alembic/core). - Not the Dashboard UI (lives in
AlembicDashboard). - Not the Codex MCP / marketplace / plugin delivery shell (lives in
AlembicPlugin). Hosts only construct anAgentRunInputand call the service layer.
These boundaries are pinned by frozen, executable manifests
(AgentRuntimeResponsibility, AgentInterfaceContract,
AgentRuntimeBoundary) and enforced by boundary lint gates (see
Verification).
┌──────────────────────────────────────────────────────────────┐
│ Surface Layer HTTP · CLI · MCP · Workflow (hosts) │
│ only construct an AgentRunInput │
└───────────────────────────────┬──────────────────────────────┘
│ AgentRunInput
▼
┌──────────────────────────────────────────────────────────────┐
│ AgentService unified entrypoint + profile compilation │
│ validate → AgentProfileCompiler → │
│ (AgentRunCoordinator fan-out?) → │
│ AgentRuntimeBuilder → runtime.execute → │
│ normalized AgentRunResult (errors degraded │
│ to structured results, never thrown) │
└───────────────────────────────┬──────────────────────────────┘
│ CompiledAgentProfile
▼
┌──────────────────────────────────────────────────────────────┐
│ AgentRuntimeBuilder profile + DI (container/tools/ai/root) │
│ → preset merge → strategy resolution → │
│ capabilities → PolicyEngine → Runtime │
└───────────────────────────────┬──────────────────────────────┘
│ new AgentRuntime(config)
▼
┌──────────────────────────────────────────────────────────────┐
│ AgentRuntime ReAct loop (Thought → Action → Observation) │
│ ├─ Capability skill / tool-allowlist composition │
│ ├─ Strategy Single / Pipeline / FanOut / Adaptive │
│ ├─ Policy Budget (hard stop) / Safety (hard block) / │
│ │ QualityGate (soft warning) │
│ └─ cross-cutting: memory / context / events / diagnostics / │
│ PCV evidence / budget compression │
└───────────────────────────────┬──────────────────────────────┘
│ tool call
▼
┌──────────────────────────────────────────────────────────────┐
│ Action Layer ToolRouter → handlers (code / terminal / │
│ knowledge / graph / memory / meta) │
│ executes actions; never selects profiles │
└──────────────────────────────────────────────────────────────┘
Baseline presets (a profile declares capabilities, strategy, and policies;
AgentProfileCompiler compiles every profile input form into one
CompiledAgentProfile):
| Preset | Capabilities | Strategy | Policies |
|---|---|---|---|
chat |
Conversation + Analysis | Single | Budget (8 turns) |
bootstrap |
Analysis + Knowledge | FanOut + Pipeline | Budget + Quality |
scan |
Analysis + Knowledge | Pipeline | Budget + Quality |
Domain runs (src/agent/runs/: plan, scan, evolution, relation, translation,
module mining) wrap the same service entrypoint with domain profiles and
result projections. AgentRunCoordinator handles fan-out: partition →
parallel child runs through AgentService.run itself → merge; child failures
become partial results instead of aborting the batch.
| Directory | Responsibility |
|---|---|
src/agent/service/ |
AgentService entrypoint, AgentRuntimeBuilder DI assembly, run contracts, system-run context factory |
src/agent/runtime/ |
AgentRuntime ReAct kernel, LoopContext, ExitController, BudgetController, ToolExecutionPipeline, LLM input assembly/measurement, hooks/events/diagnostics, frozen interface contracts, PCV node evidence (observe-only) |
src/agent/profiles/ |
Serializable profile definitions, AgentProfileCompiler, registries; presets/ holds the runtime base blocks (chat/insight/evolution — Capability+Strategy+Policy compositions that stay out of serializable profiles by design) |
src/agent/strategies/ |
Single / FanOut / Adaptive / Pipeline orchestration |
src/agent/policies/ |
PolicyEngine with Budget / Safety / QualityGate policies |
src/agent/memory/ + src/agent/evidence/ |
Three-tier memory (ActiveContext working / SessionStore session / PersistentMemory SQLite semantic) coordinated by MemoryCoordinator, plus EpisodicConsolidator; evidence/EvidenceCollector supplies grounded evidence (domain/ is now a thin re-export shell) |
src/agent/context/ |
ContextWindow (staged progressive compression), ExplorationTracker, plan tracking, nudges |
src/agent/prompts/ + src/agent/evaluation/ |
prompts/ holds persona/prompt text and retry/repair copy only; evaluation/ holds the quality gates, analysis-artifact builders, gate evaluators, and pipeline stage builders split out of the old insightGate |
src/agent/runs/ + coordination/ + tasks/ |
Domain runs, fan-out coordination, host task handlers |
src/ai/ |
AiProvider abstraction, LLMGateway, per-vendor transports, ModelRegistry, reliability, ParameterGuard, structured output |
src/tools/ |
Kernel contracts, UnifiedToolCatalog, runtime registry/router, handlers, terminal safety, output compressor + CLI parsers, DeltaCache; runtime/toolsets/ packages scenario toolsets plus the CapabilityRegistry (key → toolset constructor) |
Subpath entrypoints (see exports in package.json): ., ./agent,
./service, ./runtime, ./prompts, ./domain, ./tasks, ./profiles,
./ai, ./tools/runtime, ./memory, ./context, ./runs, ./production,
./evaluation. The last three are curated strict-production facades; internal
run families, prompts, stage/gate authority, judge calibration, fixtures, and
provider runners remain private.
Internal imports use the #agent/*, #ai/*, #shared/*, #tools/* aliases
(resolved to src/ under the alembic-dev condition, dist/ otherwise).
- Structured results, never leaked exceptions — single-run execution
errors are degraded into a complete
AgentRunResultwith a five-state status (success / blocked / aborted / timeout / error); the frozenAgentInterfaceContractpins the result branches, the ordinary-output policy, and the failure taxonomy. - Budget compresses, exit decides — session-budget thresholds only
trigger staged context compression; termination belongs to max-iterations /
timeout /
ExitControllerexit signals, with a forced-summary fallback so the final reply is never empty. - Tool safety —
terminalruns behind a global dangerous-command blocklist plus a read-only allowlist, sandboxed when available (audited on degradation);code.writeenforces a read-before-write freshness (TOCTOU) gate backed by a run-scoped sharedDeltaCache. - Observability first — hooks, an event bus, a diagnostics collector, and
the observe-only PCV node-evidence engine (grounding enforcement defaults to
off); every fallback / degraded / retry path logs its trigger and choice. - Token discipline — LLM input assembly is measured and budget-trimmed; tool outputs go through an ANSI-strip → fold → dedicated-parser compression pipeline (git / grep / test / lint / tree / package parsers) with head+tail-preserving truncation.
Workspace development intentionally consumes Core through the adjacent source checkout (local-source-first baseline):
"@alembic/core": "file:../AlembicCore"npm install
npm run build # tsc -> dist/
npm test # vitest run (mock providers; no real API keys required)Runtime dependencies: @alembic/core, better-sqlite3, drizzle-orm,
undici.
npm run check is the full gate chain: typecheck, Biome lint, and the
boundary/contract gates —
| Gate | Enforces |
|---|---|
lint:agent-import-boundary / lint:core-import-boundary |
package-entry imports only; no reaching into Core internals |
lint:public-api-boundary + smoke:public-signatures |
frozen public API surface and signatures |
smoke:strict-consumer |
plain-Node runtime and NodeNext type imports from the linked Alembic checkout; strict deep paths remain blocked |
lint:layer-contract / lint:space-edges |
layering and module-edge rules |
lint:doctrine |
side-effect doctrine — no import-time work, effects flow through injected ports (see docs/side-effect-doctrine-census.md) |
lint:naming / lint:retired-symbols |
naming rules; retired symbols stay dead |
verify:validation-floor |
minimum validation floor |
test |
vitest suite (test/), including interface-contract, terminal-safety, and PCV observe-only characterization/acceptance tests |
AI provider changes must pass with mock providers — tests never depend on real
API keys. Declared entrypoint side effects are pinned in
docs/entrypoint-effects.md and test/entrypoint-effects.test.ts.
Publish previews are staged separately:
npm run release:pack-previewrelease:stage builds and stages a publish package under tmp/release/; the
staged manifest replaces the local file:../AlembicCore dependency with the
registry @alembic/core version and records the Core source commit in
.alembic-source.json. prepack runs release:package-guard, so a raw
npm pack from the repo root cannot ship the development manifest.
MIT