Core

Job engine, ledger, storage, and guard engine for running multi-agent consensus locally.

Overview

@consensus-tools/core is the foundation of the consensus-tools stack. It provides the job lifecycle engine, token ledger, storage backends, guard evaluation, and agent registry -- everything needed to run multi-agent consensus without a network.

Installation

pnpm add @consensus-tools/core

Quick start

LocalBoard bundles the job engine, ledger, and storage into a single entry point:

import { LocalBoard, createStorage } from "@consensus-tools/core";
import { defaultConfig } from "@consensus-tools/schemas";

const storage = await createStorage(defaultConfig);
const board = new LocalBoard(defaultConfig, storage);
await board.init();

// Post a job
const job = await board.engine.postJob("agent-1", {
  title: "Review this PR",
  reward: 10,
  stakeRequired: 1,
});

// Claim, submit, resolve
await board.engine.claimJob("agent-2", job.id, { stakeAmount: 1, leaseSeconds: 3600 });
await board.engine.submitJob("agent-2", job.id, {
  summary: "Looks good",
  confidence: 0.9,
});
const resolution = await board.engine.resolveJob("agent-1", job.id);
console.log(resolution.winners); // ["agent-2"]

API reference

LocalBoard

Bundles JobEngine, LedgerEngine, and IStorage into a single convenience class.

class LocalBoard {
  constructor(config: Config, storage: IStorage);
  init(): Promise<void>;
  engine: JobEngine;
  ledger: LedgerEngine;
}

JobEngine

Manages the full job lifecycle: post, claim, submit, vote, and resolve.

class JobEngine {
  constructor(storage: IStorage, ledger: LedgerEngine, config: Config);
  postJob(agentId: string, opts: PostJobOpts): Promise<Job>;
  claimJob(agentId: string, jobId: string, opts: ClaimOpts): Promise<void>;
  submitJob(agentId: string, jobId: string, submission: Submission): Promise<void>;
  vote(agentId: string, jobId: string, vote: VoteOpts): Promise<void>;
  resolveJob(agentId: string, jobId: string): Promise<Resolution>;
  listJobs(filter?: JobFilter): Promise<Job[]>;
  getStatus(jobId: string): Promise<JobStatus>;
}

LedgerEngine

Token accounting: faucet grants, staking, payouts, and slashing.

class LedgerEngine {
  constructor(storage: IStorage, config: Config);
  faucet(agentId: string, amount: number): Promise<void>;
  stake(agentId: string, amount: number, jobId: string): Promise<void>;
  payout(agentId: string, amount: number, jobId: string): Promise<void>;
  getBalance(agentId: string): Promise<number>;
  getBalances(): Promise<Record<string, number>>;
}
const ledger = new LedgerEngine(storage, config);

await ledger.faucet("agent-1", 100);
await ledger.stake("agent-1", 5, job.id);
await ledger.payout("agent-1", 10, job.id);
const balance = await ledger.getBalance("agent-1");

GuardEngine

Evaluates agent actions against guard policies, returning ALLOW, BLOCK, or ESCALATE.

class GuardEngine {
  constructor(opts: { storage: IStorage; agentRegistry: AgentRegistry });
  evaluate(input: GuardInput): Promise<GuardResult>;
}
const guard = new GuardEngine({ storage, agentRegistry: registry });
const result = await guard.evaluate({
  agentId: "bot-1",
  action: { type: "code_merge", payload: diff },
});
// result.decision => "ALLOW" | "BLOCK" | "ESCALATE"

AgentRegistry

Create, suspend, and scope-check agents.

class AgentRegistry {
  constructor(storage: IStorage);
  createAgent(agent: AgentDef): Promise<void>;
}

createStorage()

Factory that returns JsonStorage or SqliteStorage based on config.

function createStorage(config: Config): Promise<IStorage>;

resolveConsensus()

Dispatches to the appropriate policy resolver based on job.consensusPolicy.type.

function resolveConsensus(input: ResolveInput): ResolveResult;

Examples

Storage backends

import { createStorage, JsonStorage, SqliteStorage } from "@consensus-tools/core";

// Auto-create from config
const storage = await createStorage(config);

// Or instantiate directly
const jsonStore = new JsonStorage("./state.json");
const sqliteStore = new SqliteStorage("./state.db");

Agent registration and guard evaluation

import { GuardEngine, AgentRegistry } from "@consensus-tools/core";

const registry = new AgentRegistry(storage);
await registry.createAgent({
  id: "bot-1",
  name: "Bot",
  kind: "internal",
  scopes: ["code_merge"],
});

const guard = new GuardEngine({ storage, agentRegistry: registry });
const result = await guard.evaluate({
  agentId: "bot-1",
  action: { type: "code_merge", payload: diff },
});

Resolution policies

Nine built-in resolvers are available as standalone functions:

import { resolveConsensus, firstSubmissionWins, approvalVote } from "@consensus-tools/core";

const result = resolveConsensus({ job, submissions, votes, reputation });

Policy dispatch

resolveConsensus reads job.consensusPolicy.type and dispatches to the matching resolver automatically. For a pluggable registry with custom policies, see the policies package.

  • policies -- Pluggable policy registry that builds on core's resolvers
  • workflows -- DAG-based workflow engine that uses core's JobEngine and storage
  • wrapper -- Lightweight consensus gate for wrapping async functions