npm package: @fulcrumhq/core
Description: The orchestration engine for multi-agent AI systems
Author: Fulcrum
Latest version: 1.0.0

# Fulcrum

**The orchestration engine for multi-agent AI systems.**

Fulcrum handles task decomposition, agent routing, parallel execution, state persistence, and failure recovery — so you can focus on building agents, not the plumbing between them.

```ts
import { Fulcrum, createAnthropicAgents, createAnthropicDecomposer, createAnthropicSynthesizer } from '@fulcrumhq/core'

const orchestrator = new Fulcrum({
  agents: createAnthropicAgents({ apiKey: process.env.ANTHROPIC_API_KEY! }),
  decompose: createAnthropicDecomposer({ apiKey: process.env.ANTHROPIC_API_KEY! }),
  synthesize: createAnthropicSynthesizer({ apiKey: process.env.ANTHROPIC_API_KEY! }),
})

const result = await orchestrator.run(
  'Research our top 3 competitors and draft a positioning document'
)

console.log(result.summary)
// → "Vercel leads on DX, Netlify on ecosystem, Cloudflare on performance..."
```

---

## Why Fulcrum

Multi-agent systems break in the same three ways:

1. **No routing** — you hardcode which agent handles what
2. **No state** — when an agent fails, you lose everything
3. **No parallelism** — tasks run one at a time even when they don't need to

Fulcrum solves all three. Tasks are decomposed by an LLM, routed to capable agents by capability type, executed in parallel waves respecting dependencies, and retried automatically on failure. State can be persisted to SQLite so runs survive process restarts.

---

## Install

```bash
npm install @fulcrumhq/core
```

Node.js 18+ required. For SQLite persistence, also install:

```bash
npm install better-sqlite3
```

---

## Quick start

### With Anthropic (Claude)

```ts
import { Fulcrum, createAnthropicAgents, createAnthropicDecomposer } from '@fulcrumhq/core'

const orchestrator = new Fulcrum({
  agents: createAnthropicAgents({ apiKey: process.env.ANTHROPIC_API_KEY! }),
  decompose: createAnthropicDecomposer({ apiKey: process.env.ANTHROPIC_API_KEY! }),
})

const result = await orchestrator.run('Write a competitive analysis of the top 3 CRMs')
console.log(result.summary)
```

### With OpenAI

```ts
import { Fulcrum, createOpenAIAgents, createOpenAIDecomposer } from '@fulcrumhq/core'

const orchestrator = new Fulcrum({
  agents: createOpenAIAgents({ apiKey: process.env.OPENAI_API_KEY!, model: 'gpt-4o' }),
  decompose: createOpenAIDecomposer({ apiKey: process.env.OPENAI_API_KEY! }),
})

const result = await orchestrator.run('Build a GTM strategy for a developer tools startup')
```

### With persistent state (SQLite)

```ts
import { Fulcrum, createAnthropicAgents, SqliteStore } from '@fulcrumhq/core'

const orchestrator = new Fulcrum({
  agents: createAnthropicAgents({ apiKey: process.env.ANTHROPIC_API_KEY! }),
  store: new SqliteStore('./fulcrum.db'),
})
```

---

## Core concepts

### Agents

An agent is anything with an `id`, a set of `capabilities`, and a `run` function.

```ts
import { Agent } from '@fulcrumhq/core'

const myAgent: Agent = {
  id: 'my-researcher',
  name: 'Custom Researcher',
  capabilities: [{ type: 'researcher' }],
  run: async (instruction, context) => {
    return await myLLM.complete(instruction)
  },
}
```

Built-in capability types: `researcher` · `writer` · `analyst` · `strategist` · `coder` · `custom`

### Task decomposition

Pass a `decompose` function to split tasks intelligently. Use `buildLLMDecomposer` to wire any LLM:

```ts
import { buildLLMDecomposer } from '@fulcrumhq/core'

const decompose = buildLLMDecomposer(async (prompt) => {
  const res = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: prompt }],
  })
  return res.choices[0].message.content ?? ''
})
```

### Parallel execution

Fulcrum builds an execution graph from `dependsOn` fields. Tasks without dependencies run concurrently. Tasks that depend on others wait for their results.

```ts
// t1 and t2 run in parallel
{ id: 't1', agentType: 'researcher', dependsOn: [] }
{ id: 't2', agentType: 'analyst',    dependsOn: [] }

// t3 waits for both
{ id: 't3', agentType: 'writer', dependsOn: ['t1', 't2'] }
```

### Failure recovery

Every task is retried up to `maxRetries` times (default: 3) with exponential backoff.

```ts
const orchestrator = new Fulcrum({
  agents: [...],
  maxRetries: 5,
  onTaskStart: (task) => console.log(`→ ${task.title}`),
  onTaskDone:  (task, result) => console.log(`✓ ${task.title} (${result.elapsed}ms)`),
  onTaskFail:  (task, error, attempt) => console.warn(`✗ attempt ${attempt}: ${error.message}`),
})
```

### Persistent state

Use `SqliteStore` to persist run state across process restarts:

```ts
import { SqliteStore } from '@fulcrumhq/core'

const store = new SqliteStore('./fulcrum.db')
const orchestrator = new Fulcrum({ agents: [...], store })
```

Or use `MemoryStore` explicitly (default behaviour):

```ts
import { MemoryStore } from '@fulcrumhq/core'
const store = new MemoryStore()
```

---

## Full API reference

### `new Fulcrum(options)`

| Option | Type | Description |
|---|---|---|
| `agents` | `Agent[]` | Required. Agents available for task execution. |
| `decompose` | `(task: string) => Promise<Task[]>` | Splits a task into subtasks. Defaults to single-task passthrough. |
| `synthesize` | `(task, results) => Promise<string>` | Combines agent outputs into a final answer. |
| `store` | `StateStore` | Persistence adapter. Defaults to in-memory. |
| `maxRetries` | `number` | Global retry limit. Default: `3`. |
| `onTaskStart` | `(task) => void` | Fires when a task begins. |
| `onTaskDone` | `(task, result) => void` | Fires when a task completes. |
| `onTaskFail` | `(task, error, attempt) => void` | Fires on each failed attempt. |

### `orchestrator.run(task)`

Returns a `RunResult`:

```ts
interface RunResult {
  runId: string
  task: string
  tasks: Task[]
  results: Map<string, TaskResult>
  summary?: string
  elapsed: number
  status: 'done' | 'partial' | 'failed'
}
```

### Adapters

| Function | Description |
|---|---|
| `createAnthropicAgent(opts, type?)` | Single Anthropic agent |
| `createAnthropicAgents(opts)` | Full set of Anthropic agents |
| `createAnthropicDecomposer(opts)` | Anthropic-powered task decomposer |
| `createAnthropicSynthesizer(opts)` | Anthropic-powered synthesizer |
| `createOpenAIAgent(opts, type?)` | Single OpenAI agent |
| `createOpenAIAgents(opts)` | Full set of OpenAI agents |
| `createOpenAIDecomposer(opts)` | OpenAI-powered task decomposer |
| `createOpenAISynthesizer(opts)` | OpenAI-powered synthesizer |

### Stores

| Class | Description |
|---|---|
| `MemoryStore` | In-memory, no persistence (default) |
| `SqliteStore(path?)` | Persistent SQLite store. Requires `better-sqlite3`. |

---

## Roadmap

- [ ] Streaming task results
- [ ] Agent load balancing across multiple instances
- [ ] Redis state store adapter
- [ ] Fulcrum Cloud — hosted runtime with dashboard and observability

---

## License

MIT © [Fulcrum](https://fulcrumhq.com)

Built in Norway. Open source from day one.

---

## Contributing

Issues and PRs welcome at [github.com/hashegsethbeenfired-web/fulcrum](https://github.com/hashegsethbeenfired-web/fulcrum).