Omnislash — the self-improving operator for your company

  • Durable Kill the box mid-run. The same turn resumes and settles exactly once.
  • Governed Nine parallel runs hit one wall — you get one approval card, not nine.
  • Self-improving It rewrites its own playbook, and only ever as a graded pull request.
  • Yours Your repo, your keys, your box — and any vendor’s agents, not one lab’s.
one run, end to end

You ask for an operation; you get a brain in your repo and a governed engine already running it.

Every run can make the next one better.
You approve the proposal and the final change.

YOUR REPOSITORYgit

Your company brain.

The playbooks, context and rules
that make this operator yours.

proven changes return here
04 /Proof before merge

Replay eligible workflows on the same inputs, with the same judge. Check the objective and guardrails. A failed candidate closes; an inconclusive result goes to a human.

Explore the loop
select a step ↗
Interactive demo

You own the brain. The engine earns every change.

Bring me one operation

You own the brain. You inherit the framework.

Same relationship a Next.js app has to its platform: the brain — markdown prompts, capability declarations, planner methods, one omnislash.config.ts — is yours, diffable and self-hosted. Everything else you inherit, not build: every mechanism this page goes on to prove, plus the stack that’s normally a three-year project. No queue wiring, no Postgres schema, no Restate handler, no retry logic, no dashboard.

yours

---
name: Competitor Watch
schedule: every day at 9am
---

## Steps

1. Collect — pricing, changelog, jobs …
2. Diff vs yesterday — what moved …
3. Classify — release / price / hiring …
…
  • --- name: Competitor Watch enabled: true schedule: every day at 9am agent: modelRef: smart@high skills: [battlecard] deliverable: storage: inline format: markdown --- ## Steps 1. Collect — pricing, changelog, jobs … constitution/Scenarios/<Category>/*.scenario.md
  • --- name: Account Manager description: Owns the book, not the ticket modelRef: smart@high skills: - discovery-call capabilities: - database:read - notification:send --- You own the account. Report what moved and what it will cost us if nobody moves. … constitution/Agents/*.agent.md
  • --- name: Ops Debrief enabled: true schedule: every weekday at 6pm agent: account-manager --- Close the day: what moved, what stalled, and the one thing that needs a human tomorrow. Report only what changed since this morning. … constitution/Heartbeats/*.heartbeat.md
  • --- name: Best Move Advice enabled: true schedule: "0 9 * * 1" agent: account-manager memoryFlush: true evaluation: enabled: true --- One move — the one with the best expected value this week, with the reasoning shown. … constitution/Heartbeats/*.heartbeat.md
  • export default restate.workflow({ name: 'dunning', handlers: { run: withInputSchema.workflow(Input, async (ctx, input) => { const draft = await runAgent(ctx, { agent: { name: 'dunning' }, prompt: `Dunning note for ${input.id}`, }); await awaitApproval(ctx, { title: 'Send it?', message: { text: draft.result ?? '', parseMode: 'plain' }, }); await kvSet(ctx, 'dunning', input.id, 'sent'); … features/<name>/code/*.pipeline.ts
  • --- name: Churn Signal event: ingest:event enabled: true agent: account-manager filter: source: hubspot type: deal.stage_changed --- A churn signal landed from {{source}}: {{type}}. Read the account's last three notes before you say anything, then say the one thing worth saying. … constitution/Hooks/*.hook.md
  • --- name: discovery-call description: How we run a discovery call — the questions, the order, the disqualifiers. NOT for renewals or QBRs. --- ## When to use A first call with a company that has not bought yet. Not a renewal. … skills/<name>/SKILL.md
  • --- name: customer-voice description: Grades a deliverable the way the customer would read it --- # Task Evaluation Read {{inputFile}} and {{outputFile}}. Would the customer act on this, or ask a question back? Name the question. # Run Evaluation … constitution/Evaluation/Methods/*.md
  • export const creditIssueTool = createTool({ name: 'credit_issue', description: 'Issue a service credit.', schema: z.object({ accountId: z.string(), amountUsd: z.number().max(500), }), risk: 'moderate', providesCapabilities: ['billing:credit'], label: 'Issue Credit', category: 'billing', async execute({ accountId, amountUsd }, ctx) { … tools/*.ts → registerTools()
  • export const hubspot = defineEventSource({ name: 'hubspot', extract({ headers, rawBody, body }) { const sig = headers['x-hubspot-signature']; if (!verify(rawBody, sig)) return null; const e = body as HubspotEvent; return { type: 'deal.stage_changed', payload: e.properties, idempotencyKey: e.eventId, }; }, }); … ingest/*.ts → defineProject({ ingest })
  • export default defineProject({ name: 'acme', rootAgent: { name: 'omni' }, bots: [ { name: 'omni', tokenEnv: 'TELEGRAM_BOT_TOKEN' }, { name: 'omni-pa', tokenEnv: 'PA_BOT_TOKEN', secretary: true }, ], locale: { timezone: 'Europe/Amsterdam' }, memory: { embeddingModel: 'text-embedding-3-small', }, ingest: { sources: [hubspot] }, tools: registerTools, services: { bot: true, worker: true, scheduler: true, webhooks: true }, … <brain root>/omnislash.config.ts
  • memory/2026/08/2026-08-13.md Acme moved the renewal to Q4 — Priya wants the migration finished before she signs, and said so twice. --- Northwind reads the weekly digest, nobody else on that account does. Send them nothing else. … memory/YYYY/MM/YYYY-MM-DD.md · memory/MEMORY.md

12 files · diffable · yours

inherited — you did not build this

infrastructure

the substrate it lives on, deploys as, and is watched through

  • One HTTP process serves the whole tool catalogue to every agent, whatever it runs under — Claude Code, Codex, OpenCode or an API model. Each turn opens a session carrying the caller’s own identity, so the same tool name resolves to a different permission set depending on who is asking, and a harness can never call a name it was never shown. Streamable HTTP on /mcp, plus stdio for desktop clientsper-session catalogue filtering, re-checked at call timeprogress and cancellation notificationsread-only resources by URI (skills, own pending cards)idle session reaper, body and session capsloopback bind + origin allowlist against DNS rebinding docs/mcp.md
  • Your agents work across every repo you own, not just the brain. A scenario names its target; each run gets its own clone of that repo whose origin is the real upstream, so a branch and a push land where you expect. Skills are handed over as absolute paths rather than copied in, so git status in someone else’s checkout stays clean. a JSON name → git-url map, cloned on deployper-run sandbox per repo, same path in Docker and local devwrite-back and an engine-opened PR from inside the runskills delivered out-of-tree so the checkout is never dirtiedevery resolved repo path validated before anything boots docs/extra-repos.md
  • Everything a run produces is a file in one declared tree: outputs handed between phases, files sent back to chat, the bytes behind a published link. Each subtree names its own lifecycle, so the retention sweeper is derived from that one table and a new subtree cannot quietly escape it. content-addressed blob store behind one routerrun artifacts as file-based context passing — manifest in, pull what you needper-task stored artifacts that outlive the run directorylarge step payloads offloaded to blobs instead of a rowTTL and size-budget reaper, oldest-firstin-chat file and folder browser with drill-down docs/artifacts.md
  • Every agent is a Restate virtual object keyed by its id; workflow runs, planners, the eval service and your own pipelines are durable handlers. Kill the process mid-run, redeploy, lose the network — the same invocation resumes where it stopped, including across a multi-day human pause, at zero compute while it waits. one durable owner per agent id — the per-agent queue is nativethe human pause holds inside the same invocationjournaled steps, replay-safe, exactly-once terminalsthe database row is a projection, never the control surfaceorphans reconciled against Restate’s own tables, not guessed proven against real Restate in the engine’s integration suite
  • The engine owns runtime — execution, queues, schema, CLI, Docker, monitoring. You own behaviour — prompts, capabilities, planner methods, your own tables, your own database instance. One typed config file is the entire contract between them, validated before the runtime boots, so your project can be open-sourced without shipping any engine source. defineProject() — one file, no codegen, no generated directoryyour Zod env schema merged into the engine’s at loadtyped extension points: tools, integrations, ingest, engagement, dispatch, lifecyclefixed directories are convention, not configurationfail-fast validation with an actionable hint, not a stack trace docs/eaaf-criteria.md
  • bot · worker · scheduler · monitoring · mcp · webhooks · pipelines · dashboard · sync all route off one entrypoint. One image to build, one to pull, one to roll back — and your brain extends it with a two-line Dockerfile that joins the engine’s workspace, so there is exactly one physical copy of every package. entrypoint command routing, dumb-init as PID 1FROM ghcr.io/omnislash-ai/engine:X.Y.Z + your own layerthree CLI harnesses and their sandbox shims baked inskill install specs baked and verified at build timecompose generated per mode, with an override file when you need one docs/distribution.md
  • Three blast radii, declared per agent: the live brain, its own git clone off a read-only baseline — independent index, HEAD and stash, sharing objects and nothing else, origin rewritten to your real upstream so a push lands — or a full bubblewrap jail that refuses to start if it cannot actually jail. runIn: live | clone | sandbox, declared in frontmatterper-scope checkouts sharing objects through git alternatesmount, PID and IPC namespaces, dying with the parentsame absolute paths inside and outside the jailpath containment on every file operationa database search path that hides engine tables from agent SQL docs/agent-isolation.md
  • Grafana, Prometheus, Loki, Sentry and a queue inspector, provisioned as code rather than clicked together — nine dashboards and forty alert rules up on the first deploy. And an alert does not only page you: it POSTs back in as an ordinary external event, where a hook wakes an agent that chooses between an idempotent fix, a pull request, or escalating to a person. nine dashboards and forty rules as code, routed to chatblackbox probes and per-container restart detectionthe firing alert re-enters through the engine’s own event doora disaster-recovery skill on the remediation path docs/observability.md
  • Anything that can POST becomes a trigger. You declare the source; the engine gives it an endpoint, authorizes it, deduplicates it twice, persists it and emits one event — where your hooks and heartbeats react. There is no provider-specific code anywhere in the engine. defineEventSource with your own extract(), returning null to refusethe endpoint provisioned for you, per sourcetwo-level dedup: Redis set-if-absent plus a database unique indexevery event persisted as an auditable rowthe ingest log and a generated event-schema catalogue in the dashboard docs/webhooks.md
  • You describe an integration once — its auth, its webhooks, its tools — and the engine registers it everywhere: MCP, worker, pipelines, chat. No per-integration boilerplate. OAuth connections live in one encrypted store that refreshes tokens in the background, so a long-running agent never wakes up logged out. defineIntegration — tools and webhooks in one validated objectregistration fan-out to every surface that builds a registryper-subject connection store, AES-256-GCM at the columnbackground refresh and best-effort upstream revokeOAuth that completes on a server with no inbound port open docs/integrations.md
  • One HTTP door into the running brain, and everything behind it is already wired: run a tool by name, fire a workflow, take an inbound event, finish an OAuth callback, serve a published artifact. Raw bodies are captured before parsing, so an HMAC signature verifies real bytes rather than re-serialized JSON. POST /tool/:name under a headless context — HITL tools unreachable by constructionPOST /event/:source for ingestyour integration routes, authorized by your own signature checkOAuth init, callback and statusthe published-artifact origin with ETag and a CSP sandboxthe endpoint catalogue rendered in the dashboard docs/webhooks.md
  • A markdown file names an event and an agent; the engine does the rest. One subscription covers the whole closed event set, so a hook added or edited while the system runs fires at its next matching event with no restart. N worker replicas collapse onto one keyed job, so it fires once, not once per replica. one file: event, agent, prompt — no subscription code anywhereexactly-once across replicas, with retries and a dead-letter queuehot reload behind a bounded probea hook naming an impossible event is caught at boot, not at 3amper-fire declared grants with a real call ceilingrun-scoped hooks that live and die with one workflow run docs/events-system.md
  • Sixteen named queues are the at-least-once substrate under everything that is not a durable handler: planning, notifications, evaluation, improvement, heartbeats, hook fires, memory operations, delivery. Job ids are derived from the event itself, so replicas collapse onto one job and retries and a dead-letter queue come free. deterministic keyed job ids derived from the payloadper-domain retry chains — eval backs off past its own leaserepeatable crons reconciled by diff, never nuke-and-pavedelayed jobs behind scheduling, snoozes and boss expirya queue inspector and depth metrics on the first deploygraceful drain with a cancellation signal into live git and agent work
  • Your tables are first-class, not "just the public schema". Two ordered, versioned migration lines run on every deploy — the engine’s own schema first, yours second, each with its own journal — so an engine upgrade and your own schema change never fight over one history. engine in its own schema, yours in public, composed by importthe table is the only source of types — rows and params derive from itgenerate / migrate / status; push never runs on an automatic pathconcurrent-index migrations with invalid-index cleanup on failurea dump sidecar with day/week/month rotation and its own probe docs/migrations.md
  • Point the database URL at RDS, Neon or Supabase and the generated compose drops its own Postgres container, its exporter and its backup sidecar. Same for Redis. Nothing about the code changes; the deployment simply stops carrying what you already pay for. external infrastructure detected from env, not toggled by a flagcompose, exporters and probes all derived from that detectiona tuned Postgres 17.9 when you would rather not run oneone image and one CLI either way
  • A photo, a voice note or a document arrives in chat and reaches the agent as a real file — one representation carried unchanged from the ingress, through the tool results, into both agent boundaries, and rebuilt into the conversation history on every later turn. The message text stays exactly what the person typed. one persistence type across every ingress, transport shape stops at the doorvoice replaces text rather than duplicating itan album arriving as N updates folded into one turnthe URL resolved at the door, so no lazy resolver leaks into the domainsending a file back blocks until it actually landed docs/attachments.md
  • One command and the substrate is up: Postgres, Redis, Prometheus and the durable runtime in containers, migrations applied by the same code path production uses, then every service started as a watched child process you can attach a debugger to. Nothing to install and nothing to wire — and the first Ctrl-C takes the containers down with it rather than orphaning them. infra in Docker, apps as watched processes with the inspector availablemigrations run through the production runner, never a dev shortcutboot a slice of the system when you only need a slicea per-app readiness gate, so one slow service never blocks the othersshutdown waits for the children, then stops compose exactly once docs/run-modes.md
  • One check library, two consumers: about forty-five checks from the CLI before you deploy, two dozen container-safe ones inside the running dashboard afterwards. Every check is wrapped and deadlined by construction, so a wedged Docker daemon or an unreachable server produces a named failure instead of a hung terminal. environment, configuration and infrastructure, every check self-describinga throw becomes a correctly-named failure; ten seconds is the ceilingyour writable paths, declared grants, eval ceilings and skill binaries all checkedthe dashboard set and the diagnostic tool derive from one sourceunpersistable and merely degraded are different verdicts, not one warning docs/doctor.md
  • One long-running service owns your brain’s git state, so no application process ever races another over a checkout. On a fixed interval it commits what the agents wrote, rebases, pushes, and refreshes the baseline that per-run sandboxes branch from. Nothing else boots until the first sync lands. a sparse checkout of exactly the writable set, and nothing elsecommit before pull, deliberately — agent work is committed, never stashedevery brain-consuming service gated on the first successful ticka rebase conflict spawns a resolver agent and holds all git until it verifies cleansync now from chat, from the dashboard, or from a push webhook docs/brain-dev/operations.md
  • Every path under the brain is exactly one of three things: git-backed and writable, image-baked and read-only, or host-bound runtime output. That one classification drives the sparse checkout, the daemon’s commit set, the container mounts and the ignore file — so "will this write survive a container recreate" is a design-time question with an answer, not a 3am discovery. one resolver feeds checkout anchors, mounts, commit set and ignore fileadditive only — a brain extends the writable set, never shrinks the baselinestructural and blast-radius paths refused where you declare themdirectories only, because the checkout anchor never matches a filenew files inside the set are hot; a new dependency still needs a build docs/runtime/contract.md
  • 104 typed events across 20 domains, each one a schema in the engine’s registry, validated where it is emitted and again where it is received. Two substrates behind one vocabulary: pub/sub for the real-time surfaces, Redis Streams with consumer groups for anything that must not miss a message. payload types derive from the schema — no hand-written event interfacespub/sub or streams, chosen per consumer rather than per eventrequest-response over pub/sub, so cross-process calls need no second channelwildcard subscriptions with typed matching, not string sniffinga brain declares its own events through the same contract docs/events-system.md
  • An optional spreadsheet UI over your own tables, provisioned by an init container that creates its own metadata database and points itself at your data. It sits behind the proxy’s basic auth in production, and turning the service off removes it from the generated compose entirely. one flag in the config, one subdomain at the proxymetadata database and data sources created for you at first bootadmin credentials enforced at the edge, not inside the appa service you can simply not run, like every other optional one
  • Set a domain and an email and the proxy becomes a Let’s Encrypt terminator with a subdomain per service — bot, dashboard, grafana, webhooks, artifacts. Certificates persist across recreates, admin vhosts sit behind basic auth, and the public URLs other features need are derived from the domain instead of being declared a second time. nine service subdomains routed from one variablecertificates in their own volume, so a redeploy does not re-issueadmin vhosts and private published artifacts behind the same credential pairwebhook and artifact origins derived, so OAuth installs need no second variablea self-signed fallback for a server that has no domain at all docs/production.md
  • One named volume per durability class, and the classes are the design. The brain’s git state is mounted whole only by the sync daemon — every other service sees per-path subpath views, so no application container can reach the .git directory it might corrupt. git state exposed to services as subpaths, never as a repositorya read-only baseline clone as the object source for per-run checkoutsrun sandboxes surviving restarts, so a paused run can still resumethe artifacts root a sibling of the brain, so a sandbox mount cannot shadow itdumps, certificates and log positions each in their own volume docs/distribution.md
  • Every failure the engine can produce carries a machine-readable code and a hint naming the next action — one taxonomy across the CLI and config layer, a typed family across the runtime. A brain author reads a code and a sentence, not a stack trace from inside a package they did not write. code, hint and a JSON form on every error the engine throwstyped families for agent, tool, service, auth and database failuresconfig validation fails before boot, with the offending field namedthe same codes reach the dashboard, not only the logs
  • One shutdown path for every app: a signal drains in-flight work through the same cancellation primitive the rest of the runtime uses, so a deploy never severs a git push mid-write or leaves an agent subprocess orphaned. A watch-mode restart is told apart from an operator’s stop, because they deserve different behaviour. one registration call gives any app the whole contractthe abort signal reaches live git and agent work, not just the HTTP servera hot-reload signal is not mistaken for a shutdowninfrastructure teardown runs exactly once, in a finally
  • The helper surface your pipeline code writes against: run an agent, block on a human approval, ask a question, call any tool through the full gateway, keep state between invocations, report progress. Every helper is journaled, so all of it replays correctly after a crash — with an escape hatch to the raw runtime for anything not yet wrapped. runAgent and its safe twin — a failure as a typed value, not a throwawaitApproval holds the handler open for as long as the human takescallTool goes through authorization, rate limiting and risk-based approvala Postgres-backed key-value with a TTL, for state across invocationsprogress that lands on the live card without polluting the step logthe durable runtime re-exported, so brain and engine share one module identity docs/restate-pipelines.md
  • Media that arrives is understood, not just stored: magic-byte type detection that outranks both the extension and what the sender claimed, image resize and conversion, PDF text extraction that falls back to rendering pages when a document turns out to be scanned, and transcription across a provider chain that fails over on its own. sniffed type wins over the extension and over the declared onea transcription chain of three providers, each enabled by its own keytranscripts cached by the file’s platform identity — first write winsPDF text, or rendered pages when there is not enough text to be usefulevery remote fetch DNS-pinned per redirect hop and capped mid-streamper-kind byte caps, with a local path allowed past the chat platform’s own limit docs/media.md
  • One command emits a standalone brain — chat-only, scheduled-ops or pipeline-heavy — already pinned to the registry and installable on its own. A drift test keeps what it generates byte-identical to the fixture the engine itself develops against, so a new brain never starts life as a stale copy of someone’s working tree. three flavors, each a working project rather than an empty folderregistry-pinned peers, so the singleton contract holds from minute onethe Dockerfile and deploy workflow are engine-owned and regenerate on upgradean override sentinel per generated file, when you do want to own it
  • One limiter in Redis, shared by every process — bot, worker, MCP and pipelines draw from the same budget instead of each keeping a private counter. Per-minute and per-day windows are checked and incremented in a single atomic script, so two containers cannot both squeeze through the last remaining call. one script per decision, returning which window was actually exceededthe metric label and the counter key are separate, so per-id limits never explode the metricsa read-only inspector over the live countersrejection arrives as a typed error the caller can branch on
  • One process discovering a dead provider trips the breaker for every container at once. Closed opens after three failures, half-opens after a cooldown, and expires on its own if nothing touches it again — all in atomic Redis scripts, so there is no window where half the fleet still hammers an endpoint the other half has given up on. closed → open → half-open, with the state shared rather than per-processa state-change callback, so a trip is announced instead of inferredper-provider state readable live, and rejections countedkeys expire by themselves — a forgotten breaker cannot wedge a provider forever
  • Every module logs through one factory: readable single lines with local timestamps while you develop, raw JSON in production. The collector discovers containers over the Docker socket, parses that JSON, and indexes the level as a label while attaching run, agent and pipeline ids as structured metadata — so you can query by id without exploding the index. one logger factory and one documented level contractcontainers discovered by their compose service name, not by configurationrun, agent, pipeline and task ids attached to every linelow-cardinality labels only, so the time-series store survives a busy dayfixed-cadence reconcilers log only when a tick actually changed something

intelligence

what it thinks with, reaches for, and learns from

  • A failed or below-threshold run is analysed, and the fix ships as a pull request against the thing that failed — the scenario’s own prompt, not the code around it. One live improvement per target, held by a unique index, so two bad runs can never open two PRs against the same file. Every settled verdict is distilled into a memory lesson the next analysis recalls: the loop compounds instead of relearning. the analyst reads the entity, the failure, the history and past lessonsYou choose whether accepting and merging improvements requires your approval or happens automaticallythe claim always releases: a dead worker settles, it never freezes the entitystanding delegation per scenario, admin-issued, ceilinged and revocablethe eval trend printed on the card you are deciding from docs/brain-dev/evaluation-and-improvement.md
  • A run is graded against the definition of done it was given, requirement by requirement — not a generic rubric — with a grounding check that catches a confident report of work that never happened, per-tool metrics and a typed failure category. Anything the engine runs unattended owes a daily grading ceiling, enforced where the money is spent rather than at parse time, so no config path can route around it. two levels: per-task definition of done plus run-level criteriathe deliverable verified from disk, not from the database copysampling by hashed rate plus a rolling per-day capgrading methods are brain files you can replacea failure taxonomy that groups entities failing the same waybooked before queued, so the reservation the cap counts is real docs/brain-dev/evaluation-and-improvement.md
  • When a run fails the engine spawns a recovery agent that diagnoses it, patches the plan blueprint itself and re-drives the run — the failure becomes an edit rather than a post-mortem. Categorised errors retry on their own, stuck tasks reset, and a process killed mid-run is swept back to a consistent state by a reconciler. a diagnosis tool, a blueprint patch and a retry, in one dialoguea patch that would orphan an existing task is rejected outrightbounded attempts, enforced inside the same compare-and-setduplicate triggers collapse onto one recovery per runa lost-run sweep for rows nothing is driving any more docs/workflow-fsm.md
  • Hybrid vector and full-text search across eight languages, deduplicated at write time, decayed exponentially, re-ranked for diversity — and searched automatically before every turn, so the agent never has to remember to remember. Every write is a git commit: diff what it learned last week, blame a bad fact, revert it. 0.7 vector / 0.3 keyword, then decay, then diversity re-rankingtwo zones: the engine-managed log and your own authored vaulta post-turn curator that saves corrections, gotchas and decisions onlya multi-process index that rebuilds and swaps itself atomicallydegrades to keyword-only rather than dying without an embedding keyevery write lands as a commit on your own branch docs/memory.md
  • CLI agents and API models sit behind one interface — the caller picks with a string and never calls a different API. And an agent is not a request: it has a durable inbox, so a message you send mid-turn is picked up at the next stopping point instead of being dropped or starting a second run. CLI mode: child process, resumable session, tools over MCPAPI mode: in-process stream, history rebuilt each turn, tools injected directlysend / enqueue / call — one verb per intent, all durably queuedinterrupt preempts without eating the message it preempteda fake harness that drives the whole state machine without a tokena stream-idle watchdog kills a silent harness instead of parking it forever docs/agent-flow.md
  • The same scenario escalates without being rewritten. Tier 1 is one markdown file and the planner works out the steps. Tier 2 locks the plan it produced into a blueprint you can edit. Tier 3 replaces the plan with typed TypeScript that still inherits the whole engine — agents, tools, human approval, memory, monitoring — as callable infrastructure. Which tier runs is decided by which files exist, not by a setting. Tier 1 — one scenario file, planned fresh each runTier 2 — a frozen blueprint you edit by hand or in the wizardTier 3 — a pipeline in code, all three durable primitivesthe engine picked by file presence, overridable in frontmatterone scenario can own a primary pipeline plus auxiliariespipeline code hot-reloads in production, not just in dev docs/automation-tiers.md
  • Tasks carry a phase number: phases run in order, everything inside a phase runs at once. A named context group runs its tasks one after another on a single shared agent that keeps its session across phases, while ungrouped tasks race in parallel — so "these three must build on each other, those five are independent" is a property of the plan rather than orchestration code you write. parallel within a phase, sequential between — read off the blueprint alonea context group keeps one agent session, across phasesa task can ask for its agent to be compacted before the next one runsoptional tasks can fail without failing the phase or the runrun status derived from the task rows, never stored and never disagreeinga resume skips finished phases and rebuilds the agent map from what completed docs/workflow-engine.md
  • Two ways to turn a goal into a plan. Cascade runs up to twelve focused stages — clarify, research, decompose, map capabilities, define done, group context, plan artifacts, review — each of which is a brain file you can rewrite. HTN does genuine recursive decomposition into a task network, bounded by construction and journaled step by step, so a crash resumes mid-tree. every stage prompt is a file in your repoeach stage validates itself and gets exactly one correction re-runclarification asks you real questions before it plansHTN linearizes its tree onto phases deterministicallya one-shot path for scenarios that do not need twelve stagesa live planning card, and cancellation that actually stops the model docs/workflow-planner.md · docs/htn-planner.md
  • An improvement pull request that touches the loop’s own measurement surface — the evaluation criteria, the improvement config — is auto-closed and the improvement fails. Enforced mechanically on the diff, not by asking a model nicely in a prompt: the thing being graded cannot edit the grader. the evaluation and improvement directories are off-limits to the loopchecked on the pull request diff, never in a promptthe analyst must say so in its summary if a criterion is genuinely wrongthe auto-accept capability is admin-only, so no approval card can mint it
  • A skill is a folder with a SKILL.md and optional scripts — the same open format Claude Code, Codex, Cursor and Copilot already read. The catalogue is three levels deep: names and descriptions in every system prompt, the body loaded when it triggers, reference files fetched on demand, so a hundred skills cost about ten thousand tokens instead of the whole window. the standard format, portable across every harnessprogressive disclosure with a graded budget, not a hard cutdeclared requirements — env, binaries, OS — checked before it is offeredinstall specs baked into the image and verified at buildper-skill enable and disable from the dashboardrecommendation without restriction: focus, never a lockout docs/skills.md
  • One JSON file decides which engine and integration tools exist for your brain — by tool or by whole category, as an allowlist or a denylist out of the same mechanism. A disabled tool is rejected by name everywhere: the gateway, MCP, the webhook door. There is no "hidden but still callable" state. layered document, resolved most-specific-firstone gate covers both listing and resolutionyour own tools are exempt — the policy cannot lock you out of themhot reload, with unknown keys warned rather than swalloweda broken file keeps the last good policy instead of stripping every tool docs/tool-registry.md
  • A task is not written once and executed. It starts as a title and a description, then accumulates its capabilities, its definition of done, its context group and its output artifacts across separate stages — each guarded by a coverage assert, so a task can never quietly lose a field between stages. id-keyed enrichment with a coverage assert at every stagecapabilities mapped before anything is authorizedthe definition of done written before the run, graded against after itcontext groups decide what shares one agent and what runs in parallelartifacts declared, then probed on disk when the task claims them
  • An agent can put a prompt on its own calendar — remind me tomorrow at 7:30, snooze this, keep nagging until it is answered. It is a delayed job with a deterministic id, so scheduling the same thing twice replaces rather than duplicates, and the turn’s authorization is replayed when it fires. one tool: same id replaces, cancel supporteddelivered through the agent’s own inbox, like any other messageauth replayed at fire time rather than re-requestedheartbeats for the recurring case, one-shots for everything else
  • One closed-format string names a model everywhere — the create wizard, the chat command, role frontmatter, your registry, the database column. claude · openai:gpt-4o · claude:openrouter:x-ai/grok-4.1 · smart@high · claude@high,codex@medium. Every name must be one the system knows: a typo fails at parse with a did-you-mean, never as a silent nonexistent role. bare harness, harness-through-router, provider:model, role word, literal chaina per-step reasoning-effort suffix from minimal to xhighCLI harness and API provider are different fields, never one overloaded nameclosed-world parse: structure case-insensitive, the model tail verbatima single ref is a chain of length one, so nothing has a failover special casethe availability gate stays separate from the grammar gate docs/llm.md
  • A line of frontmatter is the whole scheduling API: schedule: every weekday at 6pm. It reconciles into a repeatable job by diff — changed entries updated, absent ones removed, leftovers reaped — and a file the engine cannot parse is held at its previous schedule rather than silently vanishing from the calendar. desired-state synchronisation, never nuke-and-paveunparsable is held; a deliberately disabled entry is reapedpipeline crons declared exactly like scenario schedulesNow / Tonight / Custom time straight from a chat carda trigger that fires against a disabled scheduler removes its own job docs/scheduler.md
  • A provider marked auto-authorize hands its consent screen to a browser agent: it logs in, takes the one-time code out of the mailbox, clicks approve. Best-effort by construction — the human card is minted either way and simply stays put if the robot fails. And a token that later dies announces itself by name in chat and is re-authorized from that card, on a server with no inbound port open. an engine-shipped browser operator role with an anti-injection promptcredentials read inside the handler, never carried on the job payloadone-shot nonce, verifier and binding — a failure asks for a fresh cardthe human consent card is minted unconditionally, so nothing is lostthe blast radius is documented rather than hidden
  • A chain is one string: claude,codex. A role word resolves to an ordered list of concrete models out of your own registry, so "smart" means what you decided it means, per brain. What is worth failing over — a dead provider, an exhausted quota — is classified rather than guessed, so a genuine error still surfaces as an error instead of quietly burning the whole chain. a role word resolves to an ordered list of concrete modelsclassification decides what is worth failing over and what is a real errorrerouting is a first-class stream event, not a log linechains are same-mode and concrete — a CLI step never silently becomes an API callthe run-level retry sits above the chain, so a blip is not a failover docs/agent-flow.md
  • Two halves of one question. The policy watches a live agent’s window and acts on the crossing — a nudge, then a compaction that queues behind whatever you already sent instead of killing it. The budget answers what filled the window before the first message: tool definitions priced at their exact wire bytes, the prompt cascade attributed section by section, the context envelope part by part. per-role marks, edge-triggered, so a compaction re-arms them by data alonethe compaction never interrupts the turn you just senton-wire cost and deferred cost never conflated into one flattering numberanything known but unpriced counts as unmeasured, never as zerofindings that name the lever: no tool deferral, unused tools, memory-heavypercentages only where the runtime actually reported a window docs/context-budget.md
  • One composer builds the system prompt for the CLI path, the API path and the budget report, so a report can never describe a prompt nobody sends. It assembles in fixed modules — identity, role, persona, environment, memory instructions, language, question policy, skills catalogue — each tagged, and each replaceable by putting a file at the same path in your own repo. engine defaults overridden file by file, not forked wholesaleevery section tagged, so the budget can attribute tokens to ita different question-enforcement file per harness, because the footguns differruntime truth injected, like the live idle timeout the subprocess dies onthe same composition used for what ships and for what is measured
  • A role is what an agent knows how to be, and it is a file. Fourteen ship with the engine — planner, coder, reviewer, evaluator, improver, boss, browser operator and the rest — and your own personas are markdown under your content roots, taking priority over the defaults. Model, capabilities and role pin at creation; skills, prompt body and context stay lazy and are re-read every run. custom personas as *.agent.md, with their own model, skills and capabilitiesthree-layer inheritance: general → role → caller, resolved once at createwhat pins and what re-reads per run is deliberate, not incidentala role can install a gate that short-circuits a turn before any costthe role type stays open — a brain ships roles the engine never heard of
  • The breadth seam. A router segment in the ref points a CLI harness — including Anthropic’s own — at any model in OpenRouter’s catalogue, currently over four hundred, without the harness knowing anything about it. The router set is closed and the whole triple lives in one column, so the model an agent actually ran on stays a fact you can query. claude:openrouter:x-ai/grok-4.1 — harness, router and model in one stringthe routers are a closed set; an unknown one fails at parseone column stores the whole ref, so history stays attributablethe API providers stay a separate seam — four direct, not routed 409 models counted live on 2026-08-13 · docs/CLAIMS.md §1
  • When a harness dies mid-task the next one does not start over. The engine drains the timeline out of your own Postgres, writes it to a file, and hands the successor a pointer it reads with its own tools — plus an instruction not to redo work whose side effects already landed. The burned attempts fold into the same ledger row, so the cost is counted once and honestly. the transcript rebuilt from your database, not from provider statea pointer, not a paste — the successor opens the file itselfusage from failed attempts banked chronologically, never double-countedhandoff files cleaned in a finally, whatever the outcomea same-harness continuation skips it, because the session resume already carries the history docs/agent-flow.md
  • One append-only table is an agent’s history, and everything reads it: the chat card, the dashboard, and the API agent rebuilding its whole context every turn. Rows are ordered by a monotonic id rather than a timestamp, and compaction deletes a prefix without renumbering, so every cursor and checkpoint stays valid across it. one write path — stream write, then persistence, then derived notificationswhat persists is a closed list; deltas collapse into their terminal rowthe system half of the prompt stored content-addressed, rejoined byte-identicallytwo turns with different prompt hashes make a cache break diffablea paused turn writes its own ledger row, so pre-pause spend is never lost
  • The plan is a YAML file next to the scenario — no blueprint table, no server-side drafts. A run freezes a snapshot at creation and never re-reads it, so editing the plan mid-flight cannot change what is already executing, and the run’s slug is minted from its own id rather than a count, which keeps the artifact directory and the git branch valid forever. the file is the source of truth; git is the only historya frozen snapshot per run, task specs derived from it in memorythe run slug unique by construction — no count, no racecontent hashes decide when a plan has actually gone stalea readable title alongside the machine-readable slug
  • How an applied improvement earns its verdict depends on what it changed. A workflow scenario is re-run over its own recent inputs and compared against the baseline grade. A heartbeat is not re-run at all — the engine watches its next natural ticks, because forcing a run would send real messages and would measure the wrong thing. Arbitrary pipeline code is never re-run to score itself. a strict majority of reruns must pass, or it counts as a regressiona regression opens a mechanical revert pull requestunvalidated is a real terminal — "not checked" never becomes "checked and fine"the deadline starts when the change went live, not when the PR openedduring an observation window the target skips sampling, so nothing is missed
  • A headless browser as a sidecar service, reachable as ordinary tools — navigate, click, read, screenshot — from every CLI harness. It comes with an engine-shipped operator role that has the browser pre-attached and an anti-injection prompt, because a page you did not write is exactly where a prompt injection lives. a service you can turn off; nothing else changes when you dothe one role allowed to carry its own MCP serversany agent can spawn it as a sub-agent for a single jobthe same role the robot consent flow drives
  • A scenario whose frontmatter stopped parsing does not silently drop off the calendar. The repairer runs ahead of every reconcile, rewrites what it can atomically on disk — so the daemon commits a diff you can read and revert — and announces both outcomes to your status channel. What it cannot repair is reported once, not on every tick. runs at start, on a manual sync, and on every content changean atomic write, so a crash never leaves half a filerepairs arrive as a reviewable commit, not a hidden mutationunrepairable files deduped per path, so one bad file is not a siren
  • Every chat turn leads with one line of context rendered from where it actually came from — chat title and id, thread root, sender, timestamp in your own timezone — framed as context rather than as instruction. It is what lets an agent answer "who asked this, and where" without guessing, and because it names the ids, the history tools are directly usable. scope-shaped: a DM says less than a group, a thread says morea channel post names its own thread root, so a reply lands in the right placetimestamps in the brain’s timezone, not the server’sassembled in a fixed order: envelope, context, steer, quote, message
  • Edit a scenario and the plan regenerates itself. Every reconcile tick hashes the manifest, the scenario files and the blueprints, skips what has not changed and what was just touched, and enqueues planning for the rest. Two layers of deduplication and a cross-process lock mean one change never plans twice, and a pass that failed halfway leaves the hash unset so the next tick retries. content hashes, not timestamps, decide what is stalea recently-modified guard, so saving mid-edit does not trigger a plana distributed lock across processes plus in-process coalescingthe hash advances only on a complete passskips and failures are events, not silence
  • A browsable catalogue of remote MCP servers with a two-click install: the official registry mirrored hourly, your own pasted entries, and whatever your config declares. Installing branches on the auth kind — an OAuth redirect, a pasted token, or nothing at all — and archival only happens after a successful non-empty sync, so a registry blip cannot wipe your catalogue. three sources: the official mirror, operator-added, and brain-declareda reverse-DNS allowlist when you want the official list curatedconnected entries pinned to the first page, computed in one batched joinarchival only after a good pass; a returning entry un-archives itselfsync results and entry counts as metrics rather than as a hope

control

who is allowed, who is watching, who owns the record

  • A question, a permission request, an approval, a typed input form, an operator stepping in — one row in one table with one event pair, not six bespoke services with six ways to get stuck. Nine parallel requests hitting the same wall collapse into a single card, because the unit of decision is you, this scenario, these capabilities — not the request; one answer fans back out and wakes all nine. six kinds × seven producers, each cell explicitly defined or refusedthe answer commits before its consequences, so a crash replays instead of re-askingresolve on any surface and the card closes on all of thema dedicated inbox chat, or your own DM if you never set oneevery interaction bound to a conversation, so timelines render without a joinanything left undispatched is swept by a reconciler, not lost docs/hitl.md · test: 9 pipelines → 1 row, 9 subscribers, 1 grant
  • Every grant carries exactly one scope — scenario, agent, heartbeat or subject — with a TTL, a call ceiling and instant revocation. Approve a subset of what was asked, or answer in free text and let the model re-read what you actually meant, with the whole correction history kept for the audit. Nothing is ever decided by a timeout: there is no fast-approve, and no silent expiry into yes. four scope kinds; a grant attached to nothing is unrepresentablemint precedence heartbeat > scenario > agent — never principal-widedeclared grants pre-authorize an automation with no card at allatomic consume under the ceiling, plus scheduled and probabilistic cleanupnothing cascades: revoking is explicit, and the audit row survives docs/grants.md
  • Forty-five routes over one brain, on one typed API and a single event stream — not a widget farm with a socket each. Everything the engine knows is addressable: runs, agents, conversations, the queue, the plan editor, cost, logs, the terminal, the environment, the capability set. 30 routers and ~250 procedures; UI types derive from them, never redeclaredone server-sent-event hub with entity-scoped invalidationyour own logo and favicon, served from the running brainthe whole thing usable from a phone59 primitives on a token system, with runtime page variants docs/dashboard-page-tree.md
  • Not a notification sink — the primary interface. Commands, declared wizard flows, inline keyboards, live cards, file exchange, voice in and voice out. Nearly everything the dashboard does, you can do from a chat on your phone, including running a pipeline handler by name. per-chat active agent and model overridemulti-step wizard flows declared, not hand-rolled per commandany pipeline handler runnable straight from a chat commandsend resilience: format degradation, group migration self-heal, rate-limit retrydeep links straight into a run or a pipeline handlerin-chat introspection — ask it what it is doing right now docs/channels.md
  • A run, a plan, a pipeline, an agent turn — each gets one card that rewrites itself in place as it happens, debounced and back-pressured, instead of a stack of progress messages you scroll past. The answer streams into its own message alongside it, so the record of what was said stays separate from the record of what was happening. one message per turn, on a slot model, throttled and back-pressuredterminal stickiness — a finished card can never revert to a live keyboardanswer text streams into its own message, off the status carda reaction on your own message as a status channel: seen, working, donea plain outcome notice for a failure that had no agent to speak for it docs/channels.md
  • A bot marked secretary answers your chosen private chats as you, with zero bot chrome visible to the other side — no cards, no keyboards, no typing indicator, no failure bubble. Your own manual replies are recorded and time-stamped, so your engagement policy can read "the owner just answered this one" and back off. the connection owner is the auth principal; counterparts are never allowlistedidentity survives disconnect, reconnect and credential rotationapproval and question cards rerouted to your control DMa per-counterpart persona, so it speaks differently to different peoplehistory predating the connection readable under a blast-radius guard docs/secretary-mode.md
  • A coordinating agent watches the same queue you do and works it by policy — auto-approving what you delegated, routing questions to specialists, escalating only what genuinely needs a person. It acts through the same tools, the same compare-and-set and the same audit trail as a human would, not a side door around them. a time-boxed run with every security knob fixed at startyou get first refusal on every card, by a configured head startit can never answer or cancel an interaction it produced itselfthe capabilities it may approve are an allowlist, not a prompt instructiona run summary: duration, turns, tools by count, decisions by kind and status
  • A conversation you continue on the dashboard shows up in the bound chat as the full conversation — delivered silently, so you are not re-pinged for something you just typed yourself. The surface that started the turn gets the notification; every other bound surface gets the quiet mirror. origin notified, everyone else served the silent copyfailed and cancelled turns advance the cursor without deliveringa card resolved on one surface loses its buttons on all of thema finished turn is guaranteed to deliver, reconciled from the rows
  • Step into a live agent’s conversation while it works, steer it with ordinary messages, then hand control back — no cancel-and-restart, no losing what the run already knows. A plain message supersedes a pending question; a permission card is never dissolved by unrelated chatter, because permissions are decided explicitly. the pending row is the session marker, single-active enforced in the databaserelease re-dispatches a continuation turn and resumes the runevery other resume path is refused while you hold the wheelfrom the dashboard panel, or straight from the chat
  • An agent that hits a capability it does not hold neither fails silently nor needs everything pre-approved: the tool returns a structured missing-grant error naming a remediation path this particular caller can actually take, and the agent asks for exactly that capability, mid-run, naming what it was doing. The escalation tool is always in scope — even for an agent that declared no capabilities at all — so there is no bootstrap hole. a missing grant is a typed tool result, not a crash and not a liethe failure sentence names this caller’s own path, not a generic onethe escalation tool rides turn one, whatever the agent declareda burst of concurrent requests coalesces onto one card, one decisionthe same primitive as the plan-level gate, not a parallel path
  • Spend per model, split by billing type and by reasoning versus execution versus cache-hit tokens, attributed down to the scenario and the agent that spent it, with trends and a plain-language read of what moved. Subscription usage and metered usage are counted separately rather than blended into one flattering number. real metered spend and phantom subscription spend split everywhere it aggregatesten pivot dimensions, including who triggered itunit economics: cost per completed run, cost per passed evaluationmoney flow as a Sankey — context → provider → modela forecast gauge and a period-over-period overlay with spike markersthreshold-gated advice: cache leverage, retry overhead, evaluation blind spots
  • A full-page visual plan editor with a planner agent sitting inside it: phases and tasks you drag, execution config, the deliverable — and a chat pane editing the same draft you are looking at. It saves to your brain repo as YAML under a compare-and-set on the file’s hash, so git is the only history and there are no server-side drafts to reconcile. a rail of every blueprint, ad-hoc and repo-baseda planner-role chat pane working on the draft in front of youdrag-and-drop phases and tasks, with execution config and deliverableatomic YAML write guarded by the hash you loadedan unsaved-work guard on navigation and on unloada raw-YAML escape hatch with lock status
  • One predicate decides what the bot reacts to and how — the single seam you customize per chat. It sees normalized signals only: scope, whether it was addressed, who forwarded what, media kinds, thread identity. No platform types ever reach your code. An ignore short-circuits before any cost: no typing indicator, no download, no agent run. the verdict can carry a steer instruction injected into that turnand an opaque context bag carried verbatim to every tool call, never through the modelengine defaults per scope: DM, group, thread, channel, businessresolved once per message and cacheda separate policy per persona on a multi-bot brain docs/brain-dev/engagement.md
  • Several live agents pinned side by side in one grid, each streaming independently, each with its own conversation drawer — a war room rather than a tab per run. Sessions belonging to one lineage collapse into a single row with a status histogram, so a heartbeat that has ticked four hundred times is one line, not four hundred. list / cards / matrix, with the layout derived from the URLlineage rows carrying session counts and per-status histogramsrun-scoped matrices: every agent attached to one run, in one gridkeyset pagination a new session cannot restarttool calls, task lists and plans render as interactive blocks, not log linesa health rollup per lineage, straight from the sidebar docs/agent-grouping.md
  • Every scheduled scenario and every heartbeat on one 24-hour timeline — cron, next fire, last run, last result, and whether the grant it needs is still covered. Plus queue depth, reconciler status and a force-reconcile button, because "why did it not fire" should be one page, not three. a gantt-style fire-time view over the next 24 hoursgrant coverage shown per scheduled entry, before it failslast result includes a tick whose delivery tool failed — not a false greenqueue stats and reconciler state beside itforce a reconcile from the page, live on scheduler events docs/heartbeats.md
  • Every tool call is metered: volume, latency percentiles, failure breakdown and which agent made it, across the whole catalogue. It is how you find the tool that is quietly failing one call in ten, or the one nobody has invoked since March. windows of 1h / 24h / 7d with a share-of-total tablebreakdowns by risk, by source and by error typea per-agent slice read from the conversation timelinedenied calls counted apart from failed onesdegrades to a notice when metrics are unreachable, never a 500
  • Every self-improvement proposal on one page: what it changed, why, the pull request, and the validation verdict scored against the baseline evaluation — including how many of the reruns actually reported back, so a thin verdict looks thin. Faceted filters and paging that costs two database round-trips regardless of page size. the proposal, its concrete suggestions and the failure text side by sidethe verdict names its challengers, not just a pass or a failfilters by status, scenario and outcomea link straight to the pull request the change ships in
  • One vocabulary for "what may this agent do": a domain:capability string carrying a risk level, an approval flag and a description. Tools declare what they provide, plan tasks declare what they require, and the two meet in the middle. Three layers merge at runtime — engine defaults, your risk overrides, your own new capabilities — with unknown keys warned and skipped rather than silently accepted. thirty-three engine domains, from email and calendar through workflow and memoryrisk is informational; the approval flag is what actually gatesa brain flips any engine default without forking the lista send capability may skip approval only when the destination cannot be free-formnew capabilities synced in and dead ones dropped, your overrides preserved docs/capabilities.md
  • Anything the engine did not write — an email body, a fetched page, a webhook payload, a tool result marked external — is fenced with cryptographic boundary markers before it reaches a model. Invisible characters are stripped and lookalike angle brackets folded, so a payload cannot forge the end of its own fence. one wrapper on every external-content path, not per-integration guessworkboundary markers a payload cannot reproducehomoglyph and fullwidth bracket foldingsuspicious patterns logged, content preserved — no silent deletion
  • Owners get every command; guests can talk, tap buttons and run the connect flow; everyone else is ignored without a reply, because an error message is itself an answer to someone probing. Channel auto-forwards and anonymous admin posts are admitted only where the bot is genuinely an administrator. two allowlists and one silent defaultguests reach the conversation, never the controlschat-on-behalf admitted only under a verified admin relationshipa positive-only admin cache, so a freshly promoted bot is never left deaf
  • An entry point can declare an input schema, and then nothing runs until it is filled: the card opens, no run row is created, and the answer re-enters through the same submit path. You can fill the fields, or say them in free text — or by voice — and the translator parses them back into the schema. a form before the run, not a half-created row waiting to be fedfree text and voice parsed back into the declared fieldsthe same mechanism mid-run, resolved through a durable waitno expiry by design — one card lives until it is answered or cancelled
  • One firehose across agents, runs, pipelines, human decisions, hooks, the scheduler and the queues — live, searchable and correlated. A collector subscribes once at boot and keeps a replay buffer mirrored into Redis, so a tab opened an hour later catches up instead of starting blank. one subscription at boot, twenty thousand entries of replay behind itthe system-versus-user split declared in the event schema, not hardcoded in the UIevery envelope keyed by the first correlation id present in the payloadvirtualized rendering, so a busy brain does not melt the tabone shared reader — feature panels filter it instead of keeping a second buffer
  • The log tail inside the dashboard, with the query built server-side from indexed labels and structured metadata — filter by run, agent or pipeline id without writing a query language. Follow has three states, and the paused one keeps counting new lines while the screen stays frozen, so the line you are reading never moves out from under you. filter by run, agent, pipeline or task id as first-class chipsoff, live and paused — pausing counts instead of losingvirtualized rows that never flash a skeleton between window slidesclick a line for the full JSON; wrap and timezone togglesdegrades to an honest notice where the log stack is not deployed
  • One agent’s whole conversation, live: messages, reasoning, work groups, plans and per-message usage. It also answers the forensic question — copy the exact full prompt that was sent, and open a diff on the turns where the system prefix moved, which is usually why a cache stopped hitting or a behaviour quietly changed. copy the full prompt, rejoined byte-identically from both stored halvesa marker on turns where the system prompt changed, opening a diffpending human decisions answerable inline in the timelinecleared conversations still reachable by deep linkstop, compact, clear, retitle, re-model and flush the inbox from the same page
  • Every public link the brain ever minted, on one page — live, expired and revoked alike. Filter by status, visibility or publisher, preview the content inline, edit the title or the expiry, flip public to private, or revoke it outright. The audit trail records who published, who replaced and who revoked. an expired link can be un-expired, because a mistake is not a one-way doorpublic ↔ private is an operator-only flipinline preview, so revoking is never a guesspublished, replaced and revoked, each attributed docs/artifact-publishing.md
  • What is connected, and what could be: every provider with its status, its env keys and its configured models, alongside the live OAuth connections with reconnect, force-refresh and revoke. The server catalogue browses on the same page, one click to install. the provider inventory read from the running config, not a static listreconnect, force a token refresh, or revoke — per connectionconnection health visible before an agent discovers it the hard waythe catalogue and your own connections side by side
  • A real shell in the browser, over server-sent events rather than a socket. Two kinds of target: the dashboard’s own shell in the brain root, and an exec into any sibling service discovered through the Docker socket. Each session keeps a scrollback ring buffer, so a dropped connection or a reloaded tab replays instead of starting over. the brain root shell, or a shell inside any running servicesibling services discovered by their compose labels, scoped to this project onlyreconnect replays the scrollback; tabs survive reloadsa hard cap on live sessions, and no remote shell at all where discovery fails
  • Named destinations declared in your config with a description the model reads, while the actual chat id resolves from a fixed environment convention that is never written down in the repo. The send tool takes the name from a closed enum, so an agent can notify without an approval card precisely because it cannot invent a destination. the public name is committed; the private id is environment-onlya missing id fails boot validation rather than at 3amtwo reserved channels: your status chat and your own direct messagedelivery confirmed by returning the id of the message that landeda raw chat id is a different capability, and that one does need approval docs/brain-dev/notifications.md
  • The status card is the control surface. It carries a control row recomputed at every transition: stop, run the queued messages now, cancel one queued message by its own preview text, and a pause anchor that says what the agent is waiting for — so a queue stuck behind a question you missed does not read as a dead bot. a live queue count with previews, excluding the one already being servedthe buttons act on durable state, so a card that survived a restart still worksa tap on a stale card acts on nothing and retires its keyboardthe pause anchor names the question, not just the state
  • One brain, several bot personalities — each with its own token, persona and engagement policy, all sharing memory, skills, grants and database. Per-chat state is keyed by chat and bot together, because in a direct message the chat id is identical across every bot you run. the persona declares the name of an env var, never a tokenthe bot id derives from the token prefix, computable in any process with no API callone live turn per personality per chat, by constructionambient response elected deterministically — nobody, or exactly oneomit the list and you have exactly today’s single-bot behaviour docs/multi-bot.md
  • A forum topic binds to an agent, so inside that topic the thread is the agent selection — no command, no prefix. Each lane has its own live turn, status card, queue and delivery cursor, which means two agents stream side by side in one chat. One coordinate carries it, so every surface-keyed mechanism keeps working unchanged. the thread is the selection; commands become thread-scopedparallel lanes, each with its own card, queue and cursorone coordinate makes routing, gating and stream rebinding work unchangeda deleted topic degrades to the main stream instead of losing messagesa card tap inside a thread operates that thread’s agent, not the chat’s
  • Is the circuit open right now — not how many rejections there were last hour. The page reads the shared breaker and the shared limiter straight out of Redis, so what you see is the state every process is actually routing on, with the cooldowns ticking down in front of you. live breaker state per provider, discovered rather than configuredthe current limiter counters beside itthe state the fleet routes on, not a derived metrica snapshot poll, plus a faster feed for the events themselves

the stack that’s normally a three-year project — ships with the engine

scale — one tick, one week of build estimate · 12 files authored, 94 modules inherited

≈1 week · you author the brain ≈3 years · the framework under it, already built 1 : 156

None of that is a roadmap. Here is the same engine running — a fleet mid-turn, a run being spent against its plan, the bill it ran up, and the checks it runs on itself — on the build this page was written against.

The brain is the part that’s yours. The engine is the part you’d hate to build — and it’s already built, and running.

receipt · file names are illustrative; every frontmatter key, path convention and API name is real — brain-example/ ships working files for nine of the eleven kinds on the card (Scenarios, Agents, Heartbeats, Hooks, skills/, tools/, *.pipeline.ts, omnislash.config.ts, memory/); the grading method and the ingest source are engine contracts that fixture does not use · docs/features.md · docs/replay.md

How your company works — pulled out of Slack, tickets and people’s heads, and safe for an agent to run.

Refunds, pricing exceptions, incident response — the knowledge that today lives in fragments and in people. Omnislash keeps it as a living, versioned map the engine can read and act on, kept current without anyone curating it.

You draw the memory lines — one for the whole company, or one per role. No agent writes outside its own.
  • writes — exactly one line, always its own. No setting points an agent at somebody else’s.
  • reads — its own, plus any line its role names. One index covers all of them, and what an agent may not see is dropped before ranking, not after.

Unset, every agent shares one line; a role gets a private one the moment its file names it. And the line rides the run, not the prompt: the write tool has no argument for it, and one in the call is stripped rather than honoured.

Two agents will eventually write the same file. Because the brain is a real repo, that surfaces as a merge conflict — not as one edit quietly overwriting another.

The sync daemon stops touching the repo, hands the merge to an agent, and tells you once. It reopens only when a full sync runs clean again — the agent saying “fixed” doesn’t count. See the mechanisms →

acme/brain live · hot-reload
  • constitution/ rules · eval methods · hooks gates every run
  • memory/ what the company knows +3 commits · today
  • skills/ SKILL.md catalog · from any git URL hot-reloaded · 2m
  • scenarios/ playbooks the engine plans and runs next · mon 07:00
before every turn coarse to fine ↓
  1. forever MEMORY.md yours 12k
  2. year 2026.md ← quarters 6k
  3. quarter 2026-Q3.md ← months
  4. month 2026-08.md ← weeks
  5. week 2026-W35.md ← days
  6. today 2026-08-25.md yours 4k
  7. the ask recall ← every rung 3k

You pick the altitudes. A year of the line is 365 logs; six files of it reach the turn with no search call, and never more than 25 000 chars however large the line grows. What the ceiling cuts off the top rung is what the bottom one hands back.

  • LLM dedup on write
  • 30-day decay ½-life
  • grounded REM backfill
  • vector + full-text · 8 languages
A git repo, not a wiki — every memory write is a commit: diffable, auditable, yours.

those four folders are not a metaphor for a UI — they are the UI

and in a pocket — a company’s knowledge is consulted where the question is asked

Agents do the work. You decide how far they can go.

Set the permissions, choose who answers approval requests, and step in when a run needs guidance. Every action and decision stays on the record.

the record · the desk screens

the 3am path · on a phone

the gate one night through it, in eight beats — then the levers are yours
1/8 · 23:41

your night runs on a schedule

scenarios fire while you sleep. tonight: ten tool calls, 23:41 to 05:30, each named by the capability it needs.

five of them are flagged

every capability carries a risk tier and an hitl flag — the flag is the gate. seven of 56 ship flagged; tonight five calls hit one and raise a card to you.

which ones is your call

your constitution flips any flag: one line in a file, reviewed like code, so no agent can. yours opens two locks, shuts one.

the night, as it runs

a flagged call does not fail. the run suspends at zero compute and waits for its answer — however long that takes.

your phone, in the morning

one card per capability, however many callers — seven emails, one tap. the runs sit parked, waiting on you.

or approve it in advance

a standing grant — one scope, a TTL, a call ceiling — approved once on your phone, or declared in the scenario. email:send never raises a card again.

or hand the night to your delegate

a boss run — time-boxed, started by hand — takes every flagged call and signs an answer sixty minutes later.

nothing waited on you. nothing was waved through.

every flagged call still got an answer — your file, your grant, or your delegate — signed and replayable. the levers are yours: flip them.

  1. 23:41state:read
  2. 00:02research:read
  3. 00:14memory:delete
  4. 01:20calendar:write
  5. 02:07docs:write
  6. 03:14email:send
  7. 03:40infrastructure:discover
  8. 03:41messaging:send
  9. 04:55sheets:write
  10. 05:30drive:delete

5 cards on your phone · 09:00

telegram · 09:00 screenshot slot · 5 cards

    10 requests 23:41 → 05:30 the hitl flag · 7 of the engine’s 56 capabilities ◇ your file moves these three, both ways no onenot flagged · it ran · logged 5 your standing grantapproved in advance · no card raised 0 your boss runyour delegate answers at +60 min · signed 0 you · 09:00suspended at zero compute 5 23:41 state:read — nightly digest — answered by no one23:41state:readnightly digest00:02 research:read — competitor sweep — answered by no one00:02research:readcompetitor sweep01:20 calendar:write — move tomorrow’s standup — answered by no one01:20calendar:writemove tomorrow’s standup02:07 docs:write — draft the weekly report — answered by no one02:07docs:writedraft the weekly report04:55 sheets:write — update the revenue tracker — answered by no one04:55sheets:writeupdate the revenue tracker00:14 memory:delete — drop 214 stale notes — answered by you00:14memory:deletedrop 214 stale notes03:14 email:send times 7 callers — replies to overnight tickets — answered by you03:14email:sendreplies to overnight tickets×703:40 infrastructure:discover — check the scale headroom — answered by you03:40infrastructure:discovercheck the scale headroom03:41 messaging:send times 9 callers — heartbeat to #ops — answered by you03:41messaging:sendheartbeat to #ops×905:30 drive:delete — purge this run’s temp exports — answered by you05:30drive:deletepurge this run’s temp exports
    10 requests · 23:41 → 05:30 the hitl flag · 7 of 56 no one not flagged · logged 5 your standing grant no card raised 0 your boss run +60 min · signed 0 you · 09:00 zero compute 5 23:41 state:read — nightly digest — answered by no one23:41state:read00:02 research:read — competitor sweep — answered by no one00:02research:read01:20 calendar:write — move tomorrow’s standup — answered by no one01:20calendar:write02:07 docs:write — draft the weekly report — answered by no one02:07docs:write04:55 sheets:write — update the revenue tracker — answered by no one04:55sheets:write00:14 memory:delete — drop 214 stale notes — answered by you00:14memory:delete03:14 email:send times 7 callers — replies to overnight tickets — answered by you03:14email:send×703:40 infrastructure:discover — check the scale headroom — answered by you03:40infrastructure:discover03:41 messaging:send times 9 callers — heartbeat to #ops — answered by you03:41messaging:send×905:30 drive:delete — purge this run’s temp exports — answered by you05:30drive:delete

    You decide how much to delegate.

    Let a boss handle approval requests for a set time, within limits you choose. Or answer them yourself and guide a run when it needs help. Every decision stays on the record.

    Boss settings

    on /agents · one run at a time

    • expires one of

      5m30m1h4ha date

      past it, every wake-up is dropped unread

    • head start one of

      0s30s1m5m

      answer inside it and the boss finds nothing to do

    • kinds any of

      questiongrant_request

      a kind left out never reaches it

    • initial holds

      hitl:write

      what the boss itself carries, for the run’s length

    • approvable may approve

      email:sendmessaging:send

      what it may hand to other agents

    • the allowlist is the boundary — the prompt is documentation
    • it can never answer or cancel a card it raised itself
    • an expired run costs nothing and cannot act

    it ends with a summary: duration · turns · tools by count · decisions by kind and status

    the wheel Three ways to step in: during a run, at an approval, and between runs.
    23:00 · inbound support, overnight done · 06:41 mid-run · 02:07
    Intercepting · Workflow held

    you · 02:07 Anything asking for a refund over $200 — park it for me. Answer the rest.

    the agent Understood. Two tickets parked for you; resuming the other eleven under the same grants.

    you · 02:09release

    Released · continuation → the task’s result
    every call
    grant request · needs approval email:send reply to ticket #4471 · approve · in part · deny
    approved · by you · 02:23 email:send this run · 13 calls · on the record
    the run suspends at zero compute → sent · 02:23
    between runs

    v14 proposed → win · PR #214 · merged by you v15 proposed → regressed · revert PR #215 streak 1 of 2 · at 2, both gates fall back to you until you re-arm

    mid-run · hold the run One button holds any live workflow run — the current turn finishes, then the run waits at zero compute. You talk to the agent under the run’s own grants, then release: it finishes the task with your guidance folded in, and that continuation is the task’s result. Every other resume path is refused while you hold it. interception · the agent panel
    every call · decide what needs approval Every capability carries a lock, and the lock’s state is one line in a file you wrote and review like code. What no grant covers raises one card. The bank above is this lock, ten of the 56 the catalogue carries. constitution/engine-capabilities.json
    between runs · define “better” The loop proposes; you drew the yardstick and it cannot redraw it — a diff that touches the measurement is rejected. A win ships as a PR you merge. A regression opens its own revert PR. Two in a row, and both gates fall back to you until you re-arm. evaluation: · improvement.autonomy · maxConsecutiveRegressions: 2

    Every AI platform hits the same wall: one critical workflow outgrows “the agent figured it out,” and you leave. Here you don’t leave — you escalate that one workflow a tier up.

    AI end-to-end handles 80–90% of operations. The rest eventually need more predictability than autonomy gives — so the dial is per workflow: keep the easy 90% AI-managed, and pull the mission-critical ones down to a locked blueprint or hand-written code.

    AI end-to-end

    for business operators

    Describe it in plain language. The Cascade planner builds the plan, durable agents run it, eval grades it, the loop improves it.

    • the plan agents
    • the steps agents
    • the runtime engine

    AI + blueprint lock

    for power users, analysts

    Let AI draft the plan, then freeze it: export the blueprint, edit tasks and DoD, lock phases. Deterministic — no re-planning per run.

    • the plan yours
    • the steps agents
    • the runtime engine

    Code-defined

    for software engineers

    Write a typed Restate pipeline in TypeScript. Every step, branch and error handler is code; agents are called as typed steps, not autonomous actors.

    • the plan yours
    • the steps yours
    • the runtime engine

    describe & run lock the blueprint engineer it — per workflow, not per account

    the same path, screen by screen

    who offers which tier · july 2026
    platform tier 1 tier 2 tier 3
    n8n · Zapier · Make visual
    LangGraph · CrewAI yespartial
    Temporal · Restate yes
    Omnislash yesyesyes

    Most platforms are built for exactly one of these tiers; Omnislash spans all three, with a path between them. A Tier-3 pipeline isn’t a separate product — it inherits the entire engine: the same agents, eval, memory, tools, HITL and scheduler the AI tiers use, called as typed steps.

    all three tiers land in the same run list, graded the same way

    what one instance runs · illustrative mix 63 workflows · one deployment
    • 50 · tier 1 — AI end-to-end
    • 10 · tier 2 — AI + blueprint lock
    • 3 · tier 3 — code-defined

    Two of these didn’t start in the column they’re standing in — they were escalated a tier, one workflow at a time, on the same instance. The other 61 never moved, and nothing had to be migrated for them.

    The internet is built for humans clicking. Agents get a surface they can read, call — and be trusted with.

    Machine-readable interfaces — catalogs, APIs, MCPs — are what let an agent work without a person driving. Omnislash ships that surface both ways: every tool declares what it does and what it risks, so an agent reads before it calls instead of scraping docs — and the same declaration makes your own product agent-ready, with no per-integration boilerplate.

    It runs the other way too — an agent can work a channel as a person, answering in your own DMs with no bot chrome. The same gate applies from the inside: every tool call it makes there is pinned to that one conversation.

    the same gate · from the phone it reaches

    The surface

    what an agent finds when it looks

    • mcp server the whole surface · stdio local · HTTP prod
    • tool registry 130+ tools · domain:capability + risk level
    • integration kit auth · webhooks · tools → provisioned
    • 80+ built in Google · Notion · Figma · MTProto · n8n
    • oauth store encrypted · auto-refresh · stays signed in

    Headless OAuth

    the redirect becomes a consent card

    1. agent hits an OAuth MCP server — headless, no browser
    2. registers itself (DCR) · PKCE · resource indicators
    3. the redirect, inverted → a durable consent card: grant calendar:read to research-agent? TTL 30 days · risk: low · via Telegram
    4. a human taps approve — hours later, from a phone · or a browser agent drives the consent itself (human card as fallback)
    5. the paused run resumes with the fresh token

    The card above is drawn. The real one — the request, the partial approval, the grant it mints — is photographed in the three phone tiles this section opens with. The full machinery — HMAC state, replay guards, one-shot PKCE, per-issuer DCR locks — is one tab away: Headless OAuth →

    16 ways in, 7 ways out — and one boundary every one of them crosses.

    Every trigger enters the same governed runtime: what is allowed to wake a run, what every path passes through on the way, and where the work goes when it leaves.

    The webhook server, cron, event bus, and notifier ship with the engine.

    ways in · what wakes it 16

    a person says so

    • a message · DM, group, or as you
    • a voice note or a file
    • an action in the dashboard
    • an answer to a card

    the clock

    • a schedule · “every weekday 9:30”
    • a heartbeat · no plan, no run
    • a one-shot it set itself

    the world

    • a signed event · your verify
    • an integration’s webhook
    • an HTTP tool call
    • an MCP call

    the system itself

    • an engine event → a hook
    • an agent → an agent
    • a grade → an improvement
    • a lost run → recovery
    • a changed file → reconcile

    what every path passes

    who is this?

    surface · actor · subject. Nothing runs anonymous, on any door.

    one durable owner

    chat · heartbeat · hook · task · pipeline step · planner stage · eval — one object, per agent. Crash and it replays; park on a human and it holds the lock.

    one gate

    capability · risk · a grant with a TTL. No grant → a typed refusal naming how THIS caller can ask.

    ways out · where it lands 7

    • a messenger · as a bot or as you
    • a connected account · 80+
    • an API you declared · n8n · a browser
    • a link you can open
    • a pull request · you merge it
    • a file
    • its own memory

    The operation improves between runs — and you can read the diff of everything it learned.

    Most automation is an open loop: it runs, and a human checks later. Here the loop closes on the record — every action lands in one searchable activity stream and a real control plane, and a failed check branches a recovery agent that patches the plan and resumes. And when the engine edits its own playbook, you choose human review or autonomous approval. The lesson is a file in your repo; the improvement is a diff. Here is one.

    observeplanexecuteverifyimproveSELF-CORRECTINGthe loop
    Fig. 01 · verify fails → plan patched → run settles

    The ring is a diagram of something already running. Here is one lap of it on the record: the run list, a run in flight, its tasks, what it cost, the grade it earned, the change it proposed about itself, and the backlog that change lands in.

    the diff — PR #214, off the run at the top of this page

    constitution/Scenarios/Finance/revenue-recovery.scenario.md

    1. - pull the week’s failed payments
    2. - retry each one, safely
    3. - retry each one, safely — but hold a card_declined until the next business day; a same-day retry re-declines and burns the customer’s bank retry limit
    4. - anything over $500 — ask finance first

    An analysis opens on a pattern, not a bad morning — two of the last five graded runs came in under the bar. Three challengers ran, and the engine reads them in this order. The first rule that answers decides.

    1. 01 evidence rule 3 of 3 answered needs 2 — half the batch
    2. 02 viability rule 2 viable · 1 failed a tie adopts nothing
    3. 03 tool_failures guard 2 0 re-declines gone
    4. 03 cost_usd guard $0.38 $0.41 inside the ±10% band
    5. 04 floors rule none declared an absolute bar, not a band
    6. 05 quality objective 0.61 0.94 read last, never first
    7. duration_ms observe 22 min 19 h far worse — and not a vote

    03 above 05 is the design: a guard past its band outranks any score the judge produced, so “cost halved, quality through the floor” never reaches the objective. Stop at 01 and the change ships unvalidated — no lesson, no revert. From 02 down, the revert opens.

    Deciding and merging are two gates, and both start as your button. Arm either, and two regressions in a row hand it straight back. The lesson is filed on a loss too: “this mutation made it worse — don’t retry it here.”

    the fence — it may move the numbers, never the ruler

    1. self-edits stay on the record — you choose human review or autonomous approval
    2. rewrites the playbook, never its own eval — a diff that moves the measurement is rejected
    3. survivors run A/B against the baseline on held-out inputs
    4. win → adopted · regression → a revert PR, held at the same gate

    Every proposal that survives the fence queues up in one backlog . The rubric fence and its cited receipts are one tab away — Self-improvement →

    Every framework says “reliable” and “safe.” Pick a failure you’ve lived — here’s the line of code that kills it.

    Eleven mechanisms a skeptical staff engineer would want to see before trusting an agent with production. Each names the failure in your vocabulary, the exact primitive that fixes it, and a test you could re-run. Use the index to jump.

    One of them no lab will ship: the labs each orchestrate their own agents. Omnislash runs all of them — claude, codex, opencode, API models — under one policy gate, with cross-harness fallover mid-task. Model fabric → What each one costs a turn →

    Durability · the failure every framework ships

    Kill the worker mid-run. It resumes the same turn — not the task from scratch.

    A HITL wait in most frameworks is a blocking thread or a from-scratch rehydrate, so a crash mid-wait loses the turn. Here the entire session is one Restate virtual-object invocation, keyed by agentId: it owns the prepare, the subprocess turns and a multi-day human pause, suspended at zero compute while still holding its exclusive per-key lock. It journals the resume handle via ctx.set before ringing the lifecycle bell, and a finally clears it on every exit — so single-writer ordering, callback identity and exactly-once settlement fall out of the live invocation for free, not rebuilt across a rehydrate.

    durable run
    run ▶ step 3 / 7
    ✕ crash
    server killed · redeploy · network lost
    ↻ reconcile orphan
    (sys_invocation = liveness oracle)
    run ▶ resume @ step 3 / 7 ← not step 1
    mailbox · HITL pause · scheduled turn · stop — all survive

    receipt · agent-vo.ts:639-666 (ctx.set before the bell) · real-Restate test agent-vo.integration.ts:508-595 asserts exactly-once settlement across a kill.

    One run in flight: phase strip, live tasks, and the rail to switch runs.

    Durability · the bug only production shows you

    You dispatch an agent and hit stop a millisecond later. The naïve design no-ops and the agent runs on.

    The agent row still reads idle — current_invocation_id is projected only after the virtual object grabs its per-key lock. So control here never trusts the read model: stop, liveness and the HITL barrier all query Restate’s sys_invocation over SQL, which is ground truth. Two details prove this was learned in production, not whiteboarded: Restate serves binary Arrow IPC unless you ask for JSON, and a finished invocation lingers ~24h as completed — so the orphan reconciler filters status != 'completed' and re-verifies each run individually. A stale batch read can never mass-false-resume.

    ground truth vs the projection
    stop fired 1ms after dispatch
    agent row.current_invocation_id
    = NULL ← projection lags
    sys_invocation status
    = running ← truth
    → gate on sys_invocation. the stop lands.
    orphan sweep: classify in ONE query (status != completed)
    re-verify EACH run before resume · recover via stealFrom CAS

    receipt · restate-client.ts:481-495,:274-311 · AgentController.ts:489-522.

    • The raw engine event log — the audit trail behind every screen above.
    • The live event stream — every domain event the engine emits, as it happens.

    Governance · the rogue-agent fear, as a database problem

    Nine parallel runs need the same permission. You get one approval card, not nine — and you’re never re-asked.

    A framework without a shared HITL ledger — which is nearly all of them — raises N prompts for N callers needing sign-off, by construction. Omnislash collapses them with one Postgres upsertON CONFLICT (dedup_key) WHERE status='pending', first-writer detected via xmax=0 — keyed on [subject, scenario, sorted-caps] with the producer omitted, so a pipeline, an agent and a workflow converge on one card. One approval fans back out to an awakeable, a paused virtual object and a workflow FSM, each wake idempotent. The decision is CAS-committed to Postgres before the grant is issued; die in that gap and a 15s reconcile sweep replays it — the human is never re-asked.

    coalesce & fan-out
    9 pipelines + 1 agent + 1 workflow ─▶ hit: calendar:write
    ON CONFLICT (dedup_key) WHERE status='pending' → 1 row, 11 subs
    operator approves ··· once
    fan-out (idempotent): awakeable · paused VO · workflow FSM
    decision committed BEFORE grant → die in gap → 15s sweep replays
    forged actionId on the wire → rejected vs the declared set
    one hitl_interactions table · 4 fragmented pipelines deleted

    receipt · grant-dedup.integration.ts:34-158 · validateApprovalActions.ts:111-124 (forged-button rejection).

    • The human-in-the-loop queue: questions, approvals and grant requests in one inbox.
    • A grant request opened — which capabilities an agent is asking for, and why.
    • Live grants — what each agent may currently do, until when, and how often.

    Isolation · “cool demo” → “I’d run it on my prod”

    The vendor’s CLI owns its own subprocess and never hands you argv. So we jail it through the one seam it exposes.

    The Claude and Codex SDKs spawn their CLI internally and expose exactly one knob — an executable-path override — so the engine points it at a bwrap shim that execs the real jail: --ro-bind / / --proc /proc --unshare-pid --unshare-ipc --die-with-parent. It binds the per-run git checkout over /app/brain so every absolute path still resolves, and binds the artifacts root RW at its own sibling absolute path — so the agent’s declared output reaches the validator while a write to /app/brain stays trapped in a throwaway clone. The boot gate probes the exact namespace combo and refuses to start if it can’t actually jail.

    the jail topology
    bwrap shim (via the SDK’s one executable-path override)
    --ro-bind / / --tmpfs /tmp --proc /proc
    --unshare-pid --unshare-ipc --die-with-parent
    bind per-run checkout → /app/brain (writes trapped, disposable)
    bind artifacts root → RW (agent write = validator read, one inode)
    per-run repo = git clone --shared --local · alternates → 0 copy · gc off
    boot gate probes the EXACT combo → can’t jail? refuses to start.

    receipt · bwrap-claude.sh:41-58 (verbatim argv) · artifactsTopology.integration.ts:115-161 (real-bwrap containment test).

    A real shell into the running container, in the browser.

    Model fabric · the outage every subscription team has lived

    Claude Code prints “resets 3:10pm (Europe/Amsterdam)”. We parse that into an epoch and pin the provider across the whole fleet.

    resilience4j and opossum are in-process and threshold-only — every worker re-discovers the same dead upstream and burns its own retry budget. Omnislash turns the provider’s own wall-clock-with-timezone recovery string into an absolute instant (regex + Intl.DateTimeFormat) and an atomic Redis-Lua breaker pins the harness open until exactly that moment — the first worker to hit the wall makes every other process fast-skip it. The runtime state itself is one string in one TEXT column. And when a chain falls over mid-task, the partial tool-use transcript is rebuilt from your own Postgres into vendor-neutral markdown that tells the successor: read this, do not redo committed work.

    one ModelRef column
    claude
    CLI harness · your Max subscription
    claude:openrouter:x-ai/grok-4.1
    same harness · Grok via env override
    openai:gpt-5.2
    in-process AI-SDK call
    claude,codex
    cross-harness fallover chain
    → billing auto-flips subscription ⇄ metered
    “resets 3:10pm (Europe/Amsterdam)” → epoch → Redis-Lua pin OPEN

    receipt · redisCircuitBreaker.integration.ts:210-214 · handoff.ts:92-102.

    The model roster: roles, fallback chains, routers and per-model pricing.

    Model fabric · the bill nothing else in your stack itemises

    Someone adds the sixtieth skill. Every agent in the fleet pays for it on every turn from then on, and no meter you own can say where the tokens went.

    A turn opens with a prefix — the tool array, the system prompt, the memory envelope — that is paid on every single turn and never shrinks. A context-window meter shows one total for the last turn and cannot attribute a byte of it. Omnislash itemises that prefix per role by assembling the real prompt rather than a description of one, then names the lever rather than the number: this role’s skills catalog is a sixth of its prefix, give it a focus list. Two figures are never conflated — what is actually on the wire on turn one, and what is priced but deferred behind tool search. And the difference between harnesses is the part only a multi-vendor engine can see at all: of the three the engine drives, exactly one hides tool schemas behind a search tool, so the same brain config that is a rounding error on one is tens of thousands of tokens a turn on another. Anything the report knows exists but could not price is counted unmeasured, never as zero — the total is an admitted lower bound, not a number that quietly omits the thing you opened it to check.

    the prefix, per delivery
    the prefix — paid EVERY turn, never shrinks
    tool definitions · system prompt · context envelope
    itemised per role
    same brain, three deliveries, three bills
    claude
    turn-1 tools on the wire · the rest deferred behind search
    codex · opencode
    no deferral primitive → the WHOLE array announced
    API model
    its capability-filtered set, injected whole
    where the report stops describing and complains
    prefix ≥ 25% of the window
    critical at 40% → trim the heaviest rows
    ≥ 30 tools priced, none deferred
    pin a deferring harness · narrow the caps
    skills catalog ≥ 15% of the prefix
    give the role a focus list
    ≥ 5 tools announced, never called by ANY agent
    disable by category
    couldn’t price it → “unmeasured”, never 0. the total is a lower bound.
    metrics down ≠ zero calls — an outage never reads as “unused”.

    receipt · mcp-wire.ts:164 (the deferring-harness list is one entry long), :232 · thresholds.ts:14-42 (every judgement number, with the rationale beside it) · estimate.ts:28-31 (two chars-per-token buckets, ≈±15%, marked ≈ on every surface) · docs/context-budget.md.

    • Context budget — what fills an agent's context before its first message, itemised per role, with the lever beside each finding.
    • The tool registry: every tool an agent can call, with its risk and HITL policy.
    • Tool call statistics — what actually gets used, how often, and how it fails.
    • The model roster: roles, fallback chains, routers and per-model pricing.

    Planning · the silent corruption one-shot planners ship

    A JSON schema can assert “an array of {taskId}”. It cannot assert “this set of task IDs equals the set produced three stages ago.”

    So one-shot planners ship a plausible, broken plan the moment the LLM silently drops task-3 while mapping capabilities. Omnislash plans in up to 11 independently schema-constrained hops, and every enrichment merge runs assertTaskCoverage — diffing the stage’s task IDs against the live set and throwing with the exact missing ID, one targeted re-prompt, then escalate. Each stage snapshots to Redis before the LLM call, so killing the worker at stage 7 resumes at stage 8 with zero re-spent tokens. The final-review stage critiques the real assembled blueprint, but its output schema has no add-task or delete-task field — the worst self-review failure mode is impossible by construction.

    the planner as a state machine
    11-stage cascade · durable to the stage · resumable mid-pipeline
    stage 1 → researchNeeded? → the ONLY ['*'] privileged stage
    greps the real repo → 1 task per discovered item
    enrich: each merge → assertTaskCoverage → drop task-3? throw w/ ID
    final review → schema-whitelisted to 5 fields → can’t add/delete a task
    kill @ stage 7 → resume @ stage 8 · 0 re-spent tokens

    receipt · stageSchemas.ts:311-340 (the 5-field review whitelist) · buildPipeline.ts:71 (coverage assertion).

    • Authoring a workflow blueprint: phases, tasks and their contracts on a board.
    • Task breakdown expanded — description, definition of done, agent and spend per task.

    Isolation · live edit vs pull request, decided at the git layer

    An agent that edits its own repo is a good demo. The question production asks is which files it may touch while it runs.

    The brain stays live: on the default rung an agent writes straight into the running checkout and a sync daemon commits and pushes — the agent never pushes. What makes that safe is that the daemon commits exactly a declared push surface and nothing else, so a write outside it is not merely “not hot”, it is never persisted — the container is writable, the write succeeds, and it vanishes on the next recreate. That silent loss is now a boot-time failure. A path in the set must be a directory, because a sparse-checkout anchor never matches a blob and a file there would lose every write. Two classes are forbidden outright, for blast radius rather than boot order: docker/ — an agent that can commit a compose override can mount the docker socket into its own container — and .github, where an edit is arbitrary code on the runner. Everything else is cold, and a live agent that needs one delegates to a rung that commits and opens a PR.

    the write surface
    runIn ladder
    live ⊂ clone (+own git) ⊂ sandbox (+bwrap)
    live (default)
    writes the running checkout · daemon commits + pushes
    clone
    own pushable clone, no jail → durable edit → PR
    sandbox
    that clone, inside the bwrap jail
    the push surface
    memory/ · constitution/ · skills/ · features/
    write outside it
    succeeds → gone on recreate → now fails at boot
    must be a directory
    a sparse anchor never matches a blob
    forbidden outright
    docker/ (socket → own container) · .github (CI = code)
    cold files
    config · tools/ · db/ → the clone rung → commit → PR

    receipt · brain-paths.ts:114-145 (the forbidden set, split structural vs blast radius) · project.ts:721-773 (the directory assertion, and the second door through contentRoots) · docs/agent-isolation.md (the ladder, and what each declaration site actually does).

    • Every artifact agents produced, content-addressed and publishable by URL.
    • What the engine proposes to change about itself after grading the run.

    Self-improvement · autonomous, because it’s fenced

    Most self-editing loops trust the model not to edit its own grader. That’s a prompt instruction it ignores the moment editing the test is the cheapest way to pass.

    The boundary is not an instruction in a prompt. One accepted proposal resolves to one list of paths, and the engine renders that same list three times — before the write, around it, and over the diff after it. The rubric sits on the unreadable side: the improver works from per-criterion feedback and never opens the thing scoring it. And the one rule no path can state — an entity's own evaluation: and improvement: blocks sit in the very file it is rewriting — is held by comparing them before and after: any move rejects the change.

    the surface one proposal runs under
    one proposal → one apply turn
    may write
    the files it named
    may not write
    eval methods · db/
    may not read
    its own rubric
    the rule no path can hold
    evaluation:
    in the file it edits
    improvement:
    any move → rejected

    receipt · protectedSurface.ts:70-97 (the three lists) · protected-paths.ts:74-77 (the rubric, closed to reading) · protectedSurface.ts:160-181 (the measurement blocks). Designed against DGM Appendix H + METR reward-hacking reports.

    • The evaluation verdict — the run graded against its own definition of done.
    • The self-improvement backlog: proposals raised by runs, with their status.

    Depth · the protocol most frameworks skip

    Vanilla MCP OAuth assumes one user at a localhost loopback redirect. Our agent is headless and the human is on a phone, hours later.

    Most agent frameworks treat MCP servers as no-auth or static bearer tokens. Omnislash implements the MCP SDK’s OAuthClientProvider so the official auth() orchestrator runs the full RFC 9728 / 8414 / 7591 / 7636 / 8707 flow unchanged — except redirectToAuthorization() doesn’t redirect a browser, it mints a durable oauth_consent row a human approves later from Telegram. The protocol scars prove someone got bitten by the real spec: HMAC-signed stateless state, a SET-NX replay guard, a GETDEL one-shot PKCE, a per-issuer DCR lock, and an RFC 7009 revoke if the token-persist fails. That consent card is the same hitl_interactions row as every other human pause.

    redirect → durable card
    agent hits OAuth-protected MCP server (headless)
    DCR (RFC 7591) → per-issuer Redis lock serializes registration
    auth() → redirectToAuthorization() → mints oauth_consent HITL row
    state = HMAC · timing-safe · SET-NX replay · GETDEL one-shot PKCE
    human taps approve in Telegram (hours later) → run resumes w/ token
    token persist fails → RFC 7009 revoke (never strand a live grant)
    one table backs: question·grant·approval·input·consent·interception

    receipt · mcp-oauth-provider.ts:148,:419-477,:303-371 · oauth-state.ts:119-189.

    • Connected third-party accounts and MCP servers.
    • A grant request opened — which capabilities an agent is asking for, and why.

    Depth · the capability that needs a fence, not a disclaimer

    An agent replying as you, in your own DMs, is one API call away. Not being able to read the rest of your account is the hard part.

    Connect a bot to Telegram Business and the engine runs turns on messages from the private chats you chose, replying on your behalf with no bot chrome at all: no status cards, no keyboards, no typing indicator, no reactions — one plain message. A failed turn is silent for the other person: no error bubble, nothing appended to a half-streamed answer; you get one plain note in your own control DM, and approval cards reroute there too. The connection id is a credential, never identity — the platform rotates it whenever you edit the connection — so state is keyed on (chat, bot, owner) and survives a disconnect and a rotation. The agent reads the real history through MTProto, including messages from before the bot existed that the Bot API can never see, and that is exactly why the fence exists: under a business chat every MTProto call is pinned to that one conversation. An account-wide tool, another chat’s id, or an explicitly named account is refused permanently. A counterpart-facing agent must not become a window into your whole account.

    acting as the owner
    someone writes to your account
    engagement gate → agent turn → one plain reply, sent as you
    status cards · keyboards · typing · reactions — all suppressed
    turn fails → they see nothing; you get one note in your control DM
    approval card → your DM, never theirs
    credential ≠ identity — the connection id rotates on every rights edit
    state keyed (chat, bot, owner) → survives disconnect + rotation
    blast radius — every MTProto call pinned to THIS chat
    dialogs · global search · a named account → refused, permanently
    your own agent, in your own DM, keeps full access

    receipt · helpers.ts:239-262 (the scope refusals, verbatim) · telegram-error.ts:35 (classified permanent, not retryable) · businessFailureNotice.ts (you get the failure, they don’t) · docs/secretary-mode.md.

    • The capability catalogue with one capability expanded to its tools and risk.
    • Live grants — what each agent may currently do, until when, and how often.

    Bring me one recurring operation. I'll show you the run.

    Pick one operation that should run itself. Tell me what it is, who owns it today, and where it breaks. I'll map it to a brain and a scenario and walk you through how it runs — durable through a crash, gated at every permission, graded against a definition of done. On the engine every receipt above points at, not on a slide.

    Prefer to dig in first? See the packages & image

    Send me the one operation: what it is, who owns it today, and where it breaks. It comes straight to me — I read every one and reply myself.

    Talk to me about your operation
    hi@omnislash.ai