Skip to content

Repository files navigation

πŸ”§ Composable Agents

A TypeScript library for building reliable agentic systems from specialized sub-agents. Deterministic runtime where LLMs fill only the gaps that cannot be codified.

TypeScript MIT License Tests

✨ Features

  • 🧩 Three axioms β€” Sequence, Signal, Condition. Everything else is derived
  • ⚑ Reactive runtime β€” agents trigger on cabinet state until convergence
  • πŸ”„ Dual modes β€” sequential pipelines or reactive execution, same agent contract
  • πŸ—οΈ Deterministic orchestration β€” pipeline order, reflexes, lessons are code, not LLM decisions
  • πŸ“¦ Cabinet protocol β€” namespaced key-value store for inter-agent communication
  • 🧠 Learning system β€” skills (permanent) and lessons (decay after quiet runs)
  • πŸ” Condition engine β€” pure queries against scope state, no side effects

πŸ“¦ Installation

npm install composable-agents

πŸš€ Quick Start

import { Controller, ConditionEngine, builtinEvaluators } from 'composable-agents';

// Create agents
const agents = new Map();
agents.set('greeter', {
  id: 'greeter',
  manifest: { id: 'greeter', type: 'code', version: '0.1.0', purpose: 'Greets user' },
  execute: async (scope) => {
    scope.blackboard.setTaskOutput('Hello, World!');
    return { status: 'success', output: 'Hello, World!' };
  },
});

// Run pipeline
const controller = new Controller();
const result = await controller.run('Say hello', {
  pipeline: [{ agent: 'greeter' }],
  agents,
  conditionEngine: new ConditionEngine(),
});

console.log(result.output); // "Hello, World!"

🧩 Three Axioms

Sequence β€” ordered execution

Agents run in declared order. Steps can be singular, sequential, or parallel.

const pipeline = [
  { agent: 'input-agent' },        // singular
  { sequence: [                     // sequential
    { agent: 'validator' },
    { agent: 'transformer' },
  ]},
  { parallel: [                     // parallel branches
    { agent: 'frontend-check' },
    { agent: 'backend-check' },
  ], join: 'all', merge: 'latest' },
];

Signal β€” orthogonal events

Reflexes and lessons flow alongside execution, not through it.

const reflexes = [{
  timing: 'post-cycle',
  condition: 'has-error',
  action: 'abort-agent',
}];

Condition β€” pure queries

No side effects. Just check state.

const conditionEngine = new ConditionEngine();
conditionEngine.registerAll(builtinEvaluators);

// cabinet-exists(path=bug/classification)
// blackboard-equals(key=task.status, value="ready")

⚑ Reactive Runtime

Agents declare triggers on cabinet state. Runtime evaluates until convergence.

// Agent manifest
{
  reactive: {
    when: 'cabinet-exists(path=bug/classification)',
    priority: 10,
  },
}

// Run reactively
const result = await controller.run(task, {
  pipeline: [{ agent: 'classify' }, { agent: 'fix' }],
  agents,
  conditionEngine,
  runtime: { mode: 'reactive', maxIterations: 50 },
});

Uses rising-edge semantics β€” agents run only when their trigger transitions from false β†’ true.

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SHIPPED PATTERNS                                     β”‚
β”‚ pipeline Β· reactive runtime Β· reflexes Β· learning    β”‚
β”‚ foreman approval loops Β· user-defined compositions   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ AXIOMS                                               β”‚
β”‚ Sequence   ordered and parallel execution            β”‚
β”‚ Signal     events orthogonal to execution            β”‚
β”‚ Condition  synchronous state queries                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ CONTROLLER MODES                                     β”‚
β”‚ sequence   explicit pipeline order                   β”‚
β”‚ reactive   trigger-driven until convergence          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ STORAGE                                              β”‚
β”‚ Blackboard typed working state                       β”‚
β”‚ Cabinet    namespaced artifact protocol              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“š Core Concepts

Agent

interface Agent {
  id: string;
  manifest: AgentManifest;
  execute(scope: ExecutionScope, signal?: AbortSignal): Promise<AgentResult>;
}

AgentManifest

{
  id: string;
  type: 'llm' | 'code' | 'composite';
  version: string;
  purpose: string;
  reactive?: { when: string; priority?: number };
  learning?: { channels: string[] };
  visibility?: { expose: { cabinet: string[] } };
}

Cabinet

Namespaced key-value store for inter-agent communication.

scope.cabinet.put('bug/classification', 'frontend');
const classification = scope.cabinet.get('bug/classification');

Blackboard

Typed working state per agent.

scope.blackboard.task.input;    // what the agent received
scope.blackboard.setTaskOutput('result');

πŸ› οΈ Built-in Agents

Agent Purpose
id Identity agent β€” declares constraints and values
job Job tracking agent
reflexes Reflex evaluation agent
learning Learning loop agent
memory Memory persistence agent
foreman Approval gate agent

πŸ“– Documentation

πŸ§ͺ Testing

cd packages/core
npm test        # 146 tests passing
npm run build   # TypeScript compile
npm run lint    # Biome check

πŸ“‚ Project Structure

composable-agents/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/           # The library
β”‚   β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”‚   β”œβ”€β”€ runtime/      # Controller, engines, signal bus
β”‚   β”‚   β”‚   β”œβ”€β”€ context/      # Scope, cabinet, blackboard
β”‚   β”‚   β”‚   β”œβ”€β”€ types/        # TypeScript interfaces
β”‚   β”‚   β”‚   β”œβ”€β”€ agents/       # Built-in agents
β”‚   β”‚   β”‚   β”œβ”€β”€ conditions/   # Built-in condition evaluators
β”‚   β”‚   β”‚   └── loader/       # YAML/JSON agent loading
β”‚   β”‚   └── tests/            # 146 tests
β”‚   └── cli/            # CLI tools
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ image-resizer/  # Multi-agent image processing
β”‚   └── story-writer/   # LLM story generation pipeline
β”œβ”€β”€ schemas/            # JSON Schemas
β”œβ”€β”€ skills/             # Pi skills
β”œβ”€β”€ SPEC.md             # Implementation contract
└── AGENTS.md           # Session instructions

🀝 Contributing

See AGENTS.md for project conventions.

πŸ“„ License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages