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
Every run can make the next one better.
You approve the proposal and the final change.
The playbooks, context and rules
that make this operator yours.
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.
You own the brain. The engine earns every change.
Bring me one operationSame 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 … …
12 files · diffable · yours
inherited — you did not build this
infrastructure
the substrate it lives on, deploys as, and is watched through
intelligence
what it thinks with, reaches for, and learns from
control
who is allowed, who is watching, who owns the record
the stack that’s normally a three-year project — ships with the engine
≈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
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.
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 →
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.
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
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
scenarios fire while you sleep. tonight: ten tool calls, 23:41 to 05:30, each named by the capability it needs.
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.
your constitution flips any flag: one line in a file, reviewed like code, so no agent can. yours opens two locks, shuts one.
a flagged call does not fail. the run suspends at zero compute and waits for its answer — however long that takes.
one card per capability, however many callers — seven emails, one tap. the runs sit parked, waiting on you.
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.
a boss run — time-boxed, started by hand — takes every flagged call and signs an answer sixty minutes later.
every flagged call still got an answer — your file, your grant, or your delegate — signed and replayable. the levers are yours: flip them.
telegram · 09:00 screenshot slot · 5 cards
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.
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
it ends with a summary: duration · turns · tools by count · decisions by kind and status
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 resultv14 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
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.
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.
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.
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.
describe & run → lock the blueprint → engineer it — per workflow, not per account
the same path, screen by screen
| platform | tier 1 | tier 2 | tier 3 |
|---|---|---|---|
| n8n · Zapier · Make | — | visual | — |
| LangGraph · CrewAI | yes | — | partial |
| Temporal · Restate | — | — | yes |
| Omnislash | yes | yes | yes |
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
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.
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
Headless OAuth
the redirect becomes a consent card
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 →
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
the clock
the world
the system itself
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
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.
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
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.
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
Every proposal that survives the fence queues up in one backlog . The rubric fence and its cited receipts are one tab away — Self-improvement →
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
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.
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.
Durability · the bug only production shows you
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.
receipt · restate-client.ts:481-495,:274-311 · AgentController.ts:489-522.
Governance · the rogue-agent fear, as a database problem
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 upsert — ON 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.
receipt · grant-dedup.integration.ts:34-158 · validateApprovalActions.ts:111-124 (forged-button rejection).
Isolation · “cool demo” → “I’d run it on my prod”
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.
receipt · bwrap-claude.sh:41-58 (verbatim argv) · artifactsTopology.integration.ts:115-161 (real-bwrap containment test).
Model fabric · the outage every subscription team has lived
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.
receipt · redisCircuitBreaker.integration.ts:210-214 · handoff.ts:92-102.
Model fabric · the bill nothing else in your stack itemises
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.
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.
Planning · the silent corruption one-shot planners ship
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.
receipt · stageSchemas.ts:311-340 (the 5-field review whitelist) · buildPipeline.ts:71 (coverage assertion).
Isolation · live edit vs pull request, decided at the git layer
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.
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).
Self-improvement · autonomous, because it’s fenced
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.
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.
Depth · the protocol most frameworks skip
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.
receipt · mcp-oauth-provider.ts:148,:419-477,:303-371 · oauth-state.ts:119-189.
Depth · the capability that needs a fence, not a disclaimer
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.
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.
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