@enfav/agent-engine
v1.0.2
Published
Wiring-engine-driven adaptive reasoning engine with declarative, versioned, hot-reloadable artifact configuration
Maintainers
Readme
@enfav/agent-engine
Wiring-engine-driven adaptive reasoning engine. Solves objectives through LLM-powered beam search with declarative, versioned, hot-reloadable artifact configuration.
Table of Contents
- Requirements
- Installation
- Quick Start
- CLI Reference
- Programmatic Usage
- UI Control Panel
- Custom Op Implementations
- Strategy Plugins
- Strategy Orchestration
- Strategy Composition (MetaStrategy)
- BaseDecisionStrategy — 5-Port Protocol
- Type Imports
- Complete Export Reference
- Environment Variables
- Building from Source
- Publishing to npm
- Project Structure
- Key Features
- License
Requirements
- Node.js >= 22.0.0
- An LLM API key (OpenAI or Anthropic)
Installation
npm install @enfav/agent-engineOr run directly without installing:
npx @enfav/agent-engine --cli "Your goal here"Quick Start
1. Set your LLM API key
export OPENAI_API_KEY="sk-..."
# or
export ANTHROPIC_API_KEY="sk-ant-..."2. Run a goal
# CLI — solve a goal and exit
npx @enfav/agent-engine --cli "Build a REST API for user management"
# UI — open the browser control panel
npx @enfav/agent-engine --ui
# Programmatic — use in your own codeimport { AgentEngine } from "@enfav/agent-engine";
const engine = new AgentEngine({
strategyId: "beam-default",
});
await engine.start();
const result = await engine.run({ goal: "Design a caching layer" });
console.log(result.runId, result.converged);
await engine.stop();CLI Reference
agent-engine --cli "goal" # Solve a goal and exit
agent-engine --ui # Open browser control panel at http://localhost:8080
agent-engine --batch 5 # Run batch of goals from portfolio
agent-engine --help # Show usageOptions
| Flag | Description |
|------|-------------|
| --cli "goal" | Headless mode — solve the goal and exit |
| --ui | Interactive mode — open the control panel |
| --batch N | Batch mode — run N goals with concurrency 2 |
| --debug | Enable debug logging |
| --watch | Enable file watching for hot-reload (cli/batch modes) |
| --profile <id> | Use a specific pipeline profile for prompt tuning |
| --strategy <id> | Use a specific strategy (default: AGENT_STRATEGY_ID env) |
Programmatic Usage
Basic Usage
import { AgentEngine } from "@enfav/agent-engine";
const engine = new AgentEngine({
strategyId: "beam-default", // optional — defaults to AGENT_STRATEGY_ID env
dataDir: "./my-data", // optional — defaults to auto-detected
debug: true, // optional — enables debug logging
});
await engine.start();
const result = await engine.run({
goal: "Design a microservices architecture for an e-commerce platform",
profileId: "detailed", // optional — pipeline profile for prompt tuning
});
console.log(`Run ${result.runId}: converged=${result.converged}`);
await engine.stop();Multiple Runs
const engine = new AgentEngine({ strategyId: "beam-default" });
await engine.start();
const goals = [
"Design a caching layer",
"Build an authentication system",
"Create a logging pipeline",
];
for (const goal of goals) {
const result = await engine.run({ goal });
console.log(`${goal}: ${result.converged ? "converged" : "timed out"}`);
}
await engine.stop();Start the UI Server Programmatically
import { AgentEngine } from "@enfav/agent-engine";
const engine = new AgentEngine({
strategyId: "beam-default",
debug: true,
});
// Register any plugins before start()
// engine.registerPlugin(myPlugin);
await engine.start();
const server = await engine.startUI(8080);
console.log("Control panel at http://localhost:8080");
// Keep process alive until Ctrl+C
process.on("SIGINT", async () => {
server.close();
await engine.stop();
process.exit(0);
});On first run, the engine automatically creates a .agent-engine/ data directory in your project with all bundled strategy configs, policies, and runtime directories. Subsequent runs reuse this directory — modified configs are preserved across upgrades (see Config Overlay).
Custom LLM Provider
Inject a custom LLM adapter instead of using env-var detection:
import { AgentEngine } from "@enfav/agent-engine";
import type { LlmProviderPort } from "@enfav/agent-engine";
const myProvider: LlmProviderPort = {
async call(context) {
// Route to your own LLM infrastructure
return { content: "...", usage: { inputTokens: 0, outputTokens: 0 } };
},
};
const engine = new AgentEngine({
strategyId: "beam-default",
llmProvider: myProvider,
});Config Overlay
Override specific config files without replacing the entire bundled configuration. Provide a partial directory matching the strategy layout — files present in the overlay replace the bundled default; absent files use bundled defaults:
const engine = new AgentEngine({
strategyId: "beam-default",
configOverlayDir: "./my-overrides",
});
// ./my-overrides/strategies/beam/decision-rules/decision-rules.json
// replaces the bundled version; all other beam configs use defaults.Access SystemContext (Advanced)
For direct access to registries, bus, and internal services:
const engine = new AgentEngine({ strategyId: "beam-default" });
await engine.start();
const sys = engine.getSystemContext();
// sys.schemaRegistry, sys.opRegistry, sys.contractRegistry, etc.
console.log(`Loaded ${sys.opRegistry.count()} ops`);
await engine.stop();UI Control Panel
Start the UI with --ui (CLI) or engine.startUI(port) (programmatic). The control panel is a full React application served from the engine's bundled assets — it works identically whether you're running from the engine source repo or from an npm-installed library.
Workspaces
The UI is organized into 5 workspaces, each with multiple tabbed panels:
Dashboard — System health overview
- Overview: Health ring (valid artifact count), active run status, goal input, alerts, version health per artifact kind
- System: Registry counts, strategy info, engine configuration
- MetaStore: Query interface for run envelopes — filter by type, run ID, candidate ID
Wiring Studio — Artifact management and visualization
- Wiring Diagram: Interactive flow graph showing op-to-op data flow with binding connections
- Dependency Graph: Full 240+ node graph of all artifact dependencies with staleness cascade visualization, filtering by kind and status
- Registry Panels (Schema, Transform, Op, Op Impl, Op Manifest, Contract, Binding, Binding Set, Strategy, Workflow, Decision Rules): CRUD browsers for each artifact kind with version history, validation, and compilation controls
- Planning / Compilation / Verification / Wiring-Res / Scheduling / Runtime: Specialized inspection panels for compiled plans, verification reports, and runtime state
Run Center — Execute and monitor runs
- Beam Search: Start runs with configurable beam width, max generations, min score, and pipeline profile selection
- Phase Runner: Step-by-step phase execution with manual control
- Op Timeline: Real-time visualization of op dispatch and completion across the run
- Event Log: Scrollable, filterable log of all bus events during a run
- Convergence: Live convergence score tracking and frontier state
Lab — Experiments and prompt tuning
- Create: Design experiments with goal, profile selection, and phase filtering
- Active / Results: Monitor running experiments, compare results across profiles
- Profiles: Browse and manage pipeline profiles (prompt tuning variants)
- Run History: Historical run browser with filtering and comparison
- Section Mapping: Inspect how artifacts map to LLM input sections
- Prompt Preview: See the fully assembled LLM prompt before execution
Analytics — Performance metrics and cost tracking
Data Persistence
All run data is persisted to the .agent-engine/ directory (or your configured dataDir):
metastore/runs/{runId}/— envelopes, event logs, wiring graph snapshots per runexperiments/— experiment records and resultsstrategies/— strategy configs (hot-reloadable — edit JSON, changes take effect on next op)policies/— logging, resilience, and signal analysis policiespricing/— per-provider cost tracking configs
WebSocket Live Updates
The UI connects via WebSocket for real-time updates. The status bar shows connection state (WS: connected), registry counts (S:43 C:34 B:33 O:34), and dependency graph health (Graph: 240 valid). All artifact mutations, run events, and convergence signals push to the UI instantly.
Custom Op Implementations
Register custom op implementations to extend the engine's capabilities:
import { AgentEngine } from "@enfav/agent-engine";
import type { OpImplementation } from "@enfav/agent-engine";
const myOp: OpImplementation = {
implementationKey: "my-custom-op",
async run(input, ctx) {
// input: Record<string, unknown> — assembled from bindings
// ctx: OpExecutionContext — runtime context (runId, branchId, llmOverrides, etc.)
const result = { summary: `Processed: ${input.goal}` };
return {
output: result,
// Optional: capture LLM input snapshot for replay/analysis
inputSnapshot: undefined,
};
},
};
const engine = new AgentEngine({ strategyId: "beam-default" });
// Register before or after start()
engine.registerImplementation("my-custom-op", myOp);
await engine.start();
const result = await engine.run({ goal: "Test custom op" });
await engine.stop();Strategy Plugins
Create entirely new reasoning strategies by implementing the StrategyModule interface:
import { AgentEngine } from "@enfav/agent-engine";
import type { StrategyModule, BootstrapContext } from "@enfav/agent-engine";
const myStrategy: StrategyModule = {
async register(ctx: BootstrapContext) {
// ctx provides access to all registries, bus, meta-store, etc.
// Register ops, implementations, schemas, contracts, bindings, etc.
// Strategy-specific artifacts self-register here (Guard 23).
},
};
const engine = new AgentEngine({ strategyId: "my-strategy" });
// Plugins MUST be registered before start()
engine.registerPlugin(myStrategy);
await engine.start();Strategy Orchestration
Strategy selection is fully config-driven — the engine never hardcodes which strategy to use. The orchestration chain:
- Config —
AgentEngine({ strategyId: "beam-default" })orAGENT_STRATEGY_IDenv var - Bootstrap — validates strategyId, creates all registries and wiring infrastructure
- Module loading — built-in strategy modules (beam, fifo, meta, scanner) self-register via
register(ctx: BootstrapContext) - Data-only discovery — scans
{dataDir}/strategies/for directories containingworkflow.json; loads declarative wiring (schemas, bindings, ops, contracts) - Kind factory wiring — each data-only strategy's
workflow.strategyKindis matched to a registeredStrategyKindFactory; the factory creates aDecidePortand registers it - Runtime — scheduler calls
decidePort.decide(ctx)→ receivesSchedulerDecisionwith next actions
Adding a Strategy Without Code
Drop JSON files matching the strategy layout convention:
{dataDir}/strategies/my-strategy/
workflow.json # strategyKind: "beam" (or "fifo", "meta", etc.)
ops/my-op/v1.json # op spec declarations
contracts/my-contract/v1.json
bindings/my-binding/v1.jsonIf workflow.strategyKind matches a registered kind factory (e.g., "beam"), the strategy is fully functional with zero TypeScript.
Key Types
| Type | Import | Purpose |
|------|--------|---------|
| StrategyModule | @enfav/agent-engine | Plugin entry point: { register(ctx) } |
| BootstrapContext | @enfav/agent-engine | DI container passed to register() — all registries, bus, meta-store |
| DecidePort | @enfav/agent-engine/types/strategy | Core decision interface: { decide(input): SchedulerDecision } |
| SchedulerDecisionContext | @enfav/agent-engine/types/strategy | Input to decide() — workflowRunId, triggeringEvent, etc. |
| SchedulerDecision | @enfav/agent-engine/types/strategy | Output from decide() — nextActions, convergenceSignal |
Strategy Composition (MetaStrategy)
The built-in meta strategy kind supports multi-stage workflows that delegate to sub-strategies. Each stage references a registered strategy by ID.
workflow.json Example
{
"strategyId": "planning-then-execution",
"strategyKind": "meta",
"version": "1",
"revisionId": "meta-v1",
"stages": [
{ "stageId": "plan", "subStrategyId": "beam-default", "index": 0 },
{ "stageId": "execute", "subStrategyId": "fifo-default", "index": 1 }
],
"stageTransitions": [
{ "from": "plan", "to": "execute", "condition": { "type": "stage-converged" } }
],
"metaConvergence": { "mode": "all-stages-complete" }
}How It Works
- MetaStrategy resolves the current stage from persisted events
- Looks up the sub-strategy via
strategyRegistry.getStrategy(stage.subStrategyId) - Delegates
decide()to the sub-strategy - On convergence: evaluates stage transition conditions → loads next stage
- When all stages complete (or threshold met): signals overall convergence
Composite DecidePort (Custom Orchestration)
For patterns beyond sequential stages, wrap multiple DecidePort instances:
import type { DecidePort, SchedulerDecisionContext, SchedulerDecision } from "@enfav/agent-engine/types/strategy";
class RoutingStrategy implements DecidePort {
constructor(
private strategies: Map<string, DecidePort>,
private router: (ctx: SchedulerDecisionContext) => string,
) {}
async decide(input: SchedulerDecisionContext): Promise<SchedulerDecision> {
const strategyId = this.router(input);
return this.strategies.get(strategyId)!.decide(input);
}
}Relevant Types
| Type | Import | Purpose |
|------|--------|---------|
| StageSpec | @enfav/agent-engine/types/strategy | Stage definition: { stageId, subStrategyId, index } |
| StageTransition | @enfav/agent-engine/types/strategy | Transition condition between stages |
| ArtifactHandoff | @enfav/agent-engine/types/strategy | Cross-stage artifact transformation |
| MetaConvergence | @enfav/agent-engine/types/strategy | Meta-level convergence policy |
BaseDecisionStrategy — 5-Port Protocol
BaseDecisionStrategy is the abstract base class for building custom decision algorithms. It orchestrates 5 ports that separate concerns:
| Port | Interface | Responsibility |
|------|-----------|----------------|
| MetaStore | DecisionMetaStorePort | Read candidate records, artifact refs from storage |
| Wiring | WiringPort | Resolve schedulable ops from the wiring graph |
| Transition | TransitionPolicyPort | Determine legal next-op candidates (transition space) |
| State | StrategyStateAdapterPort<S, V> | Load algorithm-specific state, build algorithm view |
| Translator | StrategyActionTranslatorPort<I> | Convert algorithm intents to SchedulerDecision |
Implementing a Custom Strategy
import { BaseDecisionStrategy } from "@enfav/agent-engine/types/strategy";
import type {
StrategyManifest,
SchedulerDecisionContext,
StrategyRuntimeContext,
TransitionSpace,
} from "@enfav/agent-engine/types/strategy";
// 1. Define your algorithm-specific types
type MyState = { /* loaded from metastore */ };
type MyView = { /* computed from state */ };
type MyIntent = { kind: "dispatch"; opSpecId: string } | { kind: "stop"; reason: string };
// 2. Extend BaseDecisionStrategy with your types
class MyStrategy extends BaseDecisionStrategy<MyState, MyView, MyIntent> {
protected async computeNextActions(args: {
input: SchedulerDecisionContext;
manifest: StrategyManifest;
runtime: StrategyRuntimeContext;
state: MyState;
algorithmView: MyView;
transitionSpace: TransitionSpace;
}): Promise<MyIntent[]> {
// Your decision logic here
return [{ kind: "dispatch", opSpecId: "..." }];
}
protected extractOpSpecId(intent: MyIntent): string | undefined {
return intent.kind === "dispatch" ? intent.opSpecId : undefined;
}
}Port Implementations
Each port is a separate class you provide to the strategy constructor:
import type {
DecisionMetaStorePort,
WiringPort,
TransitionPolicyPort,
StrategyStateAdapterPort,
StrategyActionTranslatorPort,
} from "@enfav/agent-engine/types/strategy";
// Wire all 5 ports into the strategy
const strategy = new MyStrategy(
metaStore, // DecisionMetaStorePort — injected from BootstrapContext
wiringEngine, // WiringPort — injected from BootstrapContext
transitionPolicy, // TransitionPolicyPort — your implementation
stateAdapter, // StrategyStateAdapterPort<MyState, MyView> — your implementation
actionTranslator, // StrategyActionTranslatorPort<MyIntent> — your implementation
);The metaStore and wiringEngine ports are provided by the engine via BootstrapContext. You implement TransitionPolicyPort, StrategyStateAdapterPort, and StrategyActionTranslatorPort with your algorithm's logic.
Type Imports
Two subpath exports provide stable type imports for library consumers:
// Core data types (run results, bus events, scheduler decisions)
import type { CandidateRecord, Envelope, SchedulerDecision } from "@enfav/agent-engine/types";
// Strategy/plugin authoring types (wiring models, decision rule DSL)
import type { StrategyWorkflow, BindingSpec, DecisionRule } from "@enfav/agent-engine/types/strategy";| Subpath | Purpose |
|---------|---------|
| @enfav/agent-engine | Engine class, bootstrap, data dir, plugin interfaces, ports |
| @enfav/agent-engine/types | Data types, schemas, policy types, bus topic constants |
| @enfav/agent-engine/types/strategy | Strategy authoring: 5-port protocol, workflow types, wiring models, op types, decision rules, compiled IR |
Complete Export Reference
@enfav/agent-engine
| Export | Kind | Description |
|--------|------|-------------|
| AgentEngine | class | Main engine: start(), stop(), run(), startUI(), registerPlugin(), registerImplementation() |
| AgentEngineConfig | type | Config: strategyId, dataDir, debug, llmProvider, configOverlayDir |
| RunOptions | type | Options for engine.run(): goal, profileId |
| RunResult | type | Result from engine.run(): runId, converged |
| bootstrap / shutdown | function | Advanced: direct bootstrap lifecycle |
| BootstrapConfig | type | Full bootstrap config (superset of AgentEngineConfig) |
| SystemContext | type | All registries, bus, meta-store — returned by getSystemContext() |
| DataDirResolver | class | Resolves data directory (dev vs installed vs env override) |
| BootstrapContext | type | DI container passed to StrategyModule.register() |
| StrategyModule | type | Plugin entry: { register(ctx: BootstrapContext): Promise<void> } |
| OpImplementation | type | Custom op: { implementationKey, run(input, ctx) } |
| OpExecutionContext | type | Runtime context for op execution |
| LlmProviderPort | type | LLM adapter interface |
| BusPort | type | Event bus interface |
| BaseRegistry<T> | class | Generic Map-backed registry base — extend for custom registries |
| PanelRegistryPort | type | UI panel registration interface for plugins |
| StrategyKindFactory | type | Factory for data-only strategy DecidePort creation |
| WsAdapterFactory | type | WebSocket adapter factory for custom live updates |
| MetaStoreWritePort | type | Store envelopes in meta-store |
| MetaStoreQueryPort | type | Query envelopes from meta-store |
@enfav/agent-engine/types
| Export | Kind | Description |
|--------|------|-------------|
| CandidateRecord | type | Candidate data record |
| CandidateRecordSchema | Zod | Zod schema for CandidateRecord |
| CandidateScoreSchema | Zod | Zod schema for candidate scores |
| Envelope | type | Bus event envelope |
| EnvelopeMeta / EnvelopeTrace | type | Envelope metadata and trace context |
| EnvelopeReference | type | Lightweight envelope reference |
| SchedulerDecision | type | Decision output from strategy |
| SchedulerDecisionContext | type | Decision input context |
| SchedulerDecisionRecord | type | Persisted decision record |
| ScheduledOpIntent | type | Scheduled operation intent |
| LlmInputContext | type | Assembled LLM prompt input |
| LlmInputContextSchema | Zod | Zod schema for LlmInputContext |
| BudgetLimits | type | Resource budget constraints |
| RetryPolicy | type | Retry behavior configuration |
| AlgorithmConfig | type | Search algorithm parameters |
| BudgetLimitsSchema / RetryPolicySchema / AlgorithmConfigSchema | Zod | Zod schemas for policy types |
| TOPIC_SCHEDULER_DECISION | const | Bus topic: scheduler decision produced |
| TOPIC_SCHEDULER_CONVERGED | const | Bus topic: scheduler converged |
| TOPIC_SCHEDULER_DISPATCH | const | Bus topic: op dispatch requested |
| TOPIC_RUN_STARTED | const | Bus topic: run started |
| TOPIC_RUN_COMPLETED | const | Bus topic: run completed |
| TOPIC_TRIGGER_FIRED | const | Bus topic: trigger evaluator fired |
| PATTERN_ARTIFACT | const | Wildcard: all artifact envelopes |
| PATTERN_EVENT | const | Wildcard: all event envelopes |
@enfav/agent-engine/types/strategy
| Export | Kind | Description |
|--------|------|-------------|
| Strategy Protocol | | |
| BaseDecisionStrategy | class | Abstract base — extend with 5-port protocol |
| DecidePort | type | { decide(input): SchedulerDecision } |
| WiringPort | type | Resolve schedulable ops from wiring graph |
| DecisionMetaStorePort | type | Read candidate records and artifact refs |
| TransitionPolicyPort | type | Determine legal next-op candidates |
| StrategyStateAdapterPort<S,V> | type | Load state, build algorithm view |
| StrategyActionTranslatorPort<I> | type | Convert intents to SchedulerDecision |
| StrategyManifest | type | Strategy identity + metadata |
| StrategyRuntimeContext | type | Runtime context passed to strategy decisions |
| TransitionSpace / TransitionCandidate | type | Legal next-op candidates |
| SchedulableActionIntent<T> | type | Algorithm intent with op resolution |
| SchedulableOpResolution | type | Resolved op from wiring graph |
| Workflow Types | | |
| StrategyWorkflow | type | Full workflow definition (loaded from workflow.json) |
| OpWiringConfig | type | Per-op wiring configuration |
| TriggerSpec / EmitSpec | type | Op trigger conditions and artifact emissions |
| EnrichmentSpec / EnrichmentOp | type | Input enrichment declarations |
| BootstrapPhaseSpec | type | Strategy bootstrap phase definition |
| ConvergencePolicy | type | Frontier convergence assessment policy |
| DiversityValidationPolicy | type | Sibling diversity validation policy |
| ComputedField | type | Computed field definitions |
| StageSpec | type | MetaStrategy stage definition |
| StageTransition | type | Stage transition condition |
| ArtifactHandoff | type | Cross-stage artifact transformation |
| MetaConvergence | type | Meta-strategy convergence policy |
| Wiring Models | | |
| BindingSpec / BindingSpecSchema | type/Zod | Binding specification |
| OpInputContract / OpInputContractSchema | type/Zod | Input contract |
| SchemaDefinition / SchemaDefinitionSchema | type/Zod | Schema definition |
| TransformDefinition / TransformDefinitionSchema | type/Zod | Transform definition |
| Op Types | | |
| OpSpec / OpSpecSchema | type/Zod | Operation declaration |
| OpManifest / OpManifestSchema | type/Zod | Op scheduling/compatibility manifest |
| Decision Rules | | |
| DecisionRule / DecisionRuleSchema | type/Zod | Single decision rule |
| DecisionRuleSet / DecisionRuleSetSchema | type/Zod | Rule set collection |
| Condition / Expression | type | Rule DSL primitives |
| Compiled IR | | |
| CompiledAssemblyPlan | type | Runtime-ready binding assembly |
| CompiledSectionAssembly | type | Section assembly descriptor |
| CompiledContributor | type | Source-to-section contributor |
| SourceDependency | type | Field dependency tracking |
| CompiledAssemblyDependencies | type | Plan dependencies |
| Port Return Types | | |
| ArtifactRecordRef | type | Lightweight metastore artifact reference |
| OpSpecRef / OpSpecRefSchema | type/Zod | Op spec reference (from DecisionMetaStorePort) |
| DecisionBasisSnapshot | type | Decision basis (optional field on SchedulerDecision) |
| SchedulerAction | type | Scheduler action union (used by StrategyPlugin) |
| WorkflowTaskGraphSnapshot | type | Task graph snapshot (from DecisionMetaStorePort) |
Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| OPENAI_API_KEY | OpenAI API key | — |
| OPENAI_MODEL | OpenAI model ID | gpt-4o |
| ANTHROPIC_API_KEY | Anthropic API key | — |
| ANTHROPIC_MODEL | Anthropic model ID | claude-sonnet-4-20250514 |
| AGENT_STRATEGY_ID | Default strategy | beam-default |
| AGENT_ENGINE_DATA_DIR | Data directory override | auto-detected |
Create a .env file in your project root:
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o
AGENT_STRATEGY_ID=beam-defaultBuilding from Source
git clone <repo-url>
cd agent-engine
npm install
# Full build (TypeScript + UI frontend + asset copy)
npm run build
# Backend only (faster, skips UI)
npm run build:backend
# Run tests
npm test # unit tests (vitest)
npm run test:e2e # Playwright e2e tests
# Development (no build needed)
npm start # default: UI mode
npm run cli -- "goal" # CLI mode via tsx
npm run ui # UI mode via tsxBuild Scripts
| Script | What it does |
|--------|-------------|
| npm run build | Full build: tsc + UI frontend + copy assets to dist/ |
| npm run build:backend | TypeScript compilation only |
| npm run build:ui | Build the React frontend |
| npm run build:copy-assets | Copy frontend build to dist/ui/frontend/dist |
| npm test | Run unit tests with vitest |
| npm run test:e2e | Run Playwright e2e tests |
Publishing to npm
First-Time Setup
Log in to npm (creates/updates
~/.npmrc):npm loginIf using a scoped package (
@enfav/agent-engine), ensure your npm org exists.
Publish Workflow
# 1. Make sure tests pass
npm test
# 2. Bump version (choose one)
npm version patch # 1.0.0 → 1.0.1 (bug fixes)
npm version minor # 1.0.0 → 1.1.0 (new features, backwards compatible)
npm version major # 1.0.0 → 2.0.0 (breaking changes)
# 3. Publish (build runs automatically via prepublishOnly hook)
npm publish --access public
# 4. Push the version tag to git
git push && git push --tagsWhat Gets Published
The files field in package.json controls what's included in the npm package:
| Included | Contents |
|----------|----------|
| dist/ | Compiled TypeScript + frontend assets |
| static/strategies/ | Declarative strategy configs (ops, bindings, schemas, etc.) |
| static/goals/ | Goal portfolio for batch mode |
| LICENSE | License file |
| README.md | This file |
Everything else (source TypeScript, tests, docs, dev configs) is excluded.
Verify Before Publishing
# See exactly what will be in the package
npm pack --dry-run
# Check package size
npm pack # creates .tgz file you can inspectRotating npm Tokens
If you accidentally expose your npm token:
- Go to https://www.npmjs.com → Avatar → Access Tokens
- Delete the compromised token immediately
- Generate New Token (Granular Access Token recommended)
- Re-authenticate locally:
npm login
Project Structure
agent-engine/
├── src/
│ ├── index.ts # Public API exports
│ ├── engine.ts # AgentEngine class
│ ├── run.ts # CLI entry point
│ ├── bootstrap.ts # System initialization
│ ├── core/ # Core protocols, ports, utilities
│ ├── machines/ # XState state machines (agent, scheduler, etc.)
│ ├── ops/ # Op specs, implementations, registries
│ ├── strategy/ # Strategy implementations (beam/, etc.)
│ ├── wiring/ # Wiring engine (registries, compilers, validators)
│ └── ui/ # HTTP server + React frontend
├── static/
│ └── strategies/ # Declarative JSON configs per strategy
│ └── beam/ # Beam search strategy artifacts
│ ├── workflow.json
│ ├── ops/ # Op spec versions
│ ├── contracts/ # Input contract versions
│ ├── bindings/ # Binding spec versions
│ └── schemas/ # Schema definition versions
├── tests/
│ ├── unit/ # Vitest unit tests
│ └── e2e/ # Playwright e2e tests
├── dist/ # Build output (git-ignored)
└── package.jsonKey Features
- Declarative wiring engine — All prompt assembly flows through versioned, hot-reloadable JSON configs
- 11-level artifact hierarchy — Schemas, transforms, contracts, ops, bindings, profiles, workflows, and strategies
- Version immutability — Every config version is permanent, enabling full replay of historical runs
- Dependency-aware cascade — Changes propagate automatically through the artifact graph
- Plugin system — Custom op implementations and data-only strategies without code changes
- Browser UI — Full CRUD, validation, compilation, and visualization for all artifact kinds
- Beam search — LLM-powered adaptive reasoning with convergence detection
- Hot-reload — Change JSON configs at runtime, no restart required
- Replay support — Every run captures a WiringGraphSnapshot for full reconstruction
License
Proprietary — see LICENSE for terms.
Copyright (c) 2025-2026 enfav llc. All rights reserved.
