Open-source agentic finance platform

A 110-agent finance hierarchy that ships to production.

CEO → 9 orchestrators → 100 workers. Deterministic policy engine. Postgres row-level tenant isolation. Immutable audit logs. MIT licensed.

The problem

01Most "AI finance" stacks are wrappers around an LLM with a prompt. They fail in production because there’s no enforceable policy layer.

02Regulated workflows (SOX, GDPR, audit) require code-level guarantees — not prompt-level asks.

03ClawKeeper separates intent (what the agent wants to do) from authority (what it’s allowed to do). The policy engine runs in TypeScript, not in the prompt.

How it works

01

Three-layer agent hierarchy

1 CEO agent (task intake, decomposition); 9 orchestrator agents (one per finance domain: AP, AR, payroll, tax, treasury, reporting, audit, compliance, FP&A); 100 worker agents (specialized routines per orchestrator).

02

Deterministic policy engine

Policies written as TypeScript functions, not natural language. Pre-execution check before any financial workflow. Block + log + alert on violation.

03

Tenant isolation

Postgres row-level security (RLS) on every table. Per-tenant JWT claims bound to query context. Append-only immutable audit logs.

110
agents
3
layers
MIT
license
RLS
Postgres

Policy engine

Agent intent. Policy check. Allow or deny — with a reason.

An agent proposes a payment. The policy function checks amount limits, tenant scope, and approval state, then returns allow/deny + reason. The deny path logs and alerts.

policy/engine.ts
// Deterministic policy engine — agent intent vs. policy check
type Intent = { type: "payment"; amountCents: number; tenantId: string; approvedBy?: string };
type Decision = { allow: boolean; reason: string };

export function evaluate(intent: Intent, ctx: { tenantId: string; limitCents: number }): Decision {
  if (intent.tenantId !== ctx.tenantId)
    return deny("tenant_scope_violation: intent crosses tenant boundary");
  if (intent.amountCents > ctx.limitCents)
    return deny(`amount_over_limit: ${intent.amountCents} > ${ctx.limitCents}`);
  if (intent.amountCents >= 10_000_00 && !intent.approvedBy)
    return deny("approval_required: payments >= $10,000 need explicit approval");
  return { allow: true, reason: "ok" };
}

function deny(reason: string): Decision {
  audit.append({ kind: "policy_deny", reason });   // append-only log
  alerts.emit({ severity: "high", reason });
  return { allow: false, reason };
}