Approve it once. Then go do something else.
That was always the promise of an agent: you set the rules, you walk away, and
the work happens without you standing over it.
Nobody actually leaves the room. You know why. The judge that waves everything
through. The retry that charges you twice. The crash at step 40 of 60. The
memory that swears it remembers. The green checkmark you don't quite believe.
0.47 is one release about one thing: making it safe to walk away.
Your rules get a spine
type: accept — the outcome gate. "The agent finished" and "the agent
succeeded" are different facts. Now there's a step that knows the difference.
A worker produces the work; a panel judges it against your rubric. Deterministic
checks run first — and reject for $0 before a single judge is paid. Then the
judges: per-judge models, an N-of-M quorum where adding a judge tightens the
panel, and a human fallback when the machines shouldn't have the last word.
Rejected work doesn't slip through and it doesn't get to beg. A rejection stops
the run, isn't retryable — a judge you ask three times is a judge you're
negotiating with — and can send the work back with the judge's critique
injected into the retry, bounded so it can never loop forever.
And every verdict writes an evidence pack: what was judged, what each judge
said, what it cost, how the vote went. Into the audit chain. A verdict you can
show someone is a verdict; anything else is a mood.
- id: review
type: accept
accept_config:
target: draft_contract_summary
checks:
- {type: contains, value: "termination"} # free
judges:
- model: sonnet
rubric: "Every obligation must trace to a clause. No invented terms."
- model: haiku
rubric: "Reject if any quoted text does not appear in the source."
on_reject: retry_target
max_rounds: 3Run it again. Pay once.
An effect ledger now records everything that leaves the building — every
outbound request, every model call — keyed to the run's lineage.
Two full runs. One POST. $0 the second time.
Replay a workflow and the completed work stays done: the invoice doesn't go out
twice, the ticket isn't created twice, the tokens you paid for aren't paid for
again. Your budget report shows it — memoized steps bill zero and still show
what the first pass paid.
And when the process dies, the run doesn't. Kill the worker at step 40 of
60. The run comes back on its own, steps 1–40 replay from the ledger at $0 with
zero duplicate sends, and the work continues from where reality left off — not
from where a checkpoint guessed. Bounded attempts, so a poisoned run fails
loudly instead of looping quietly.
That's the difference between retry and resume. Retry does it again. Resume
picks it up.
Bring your own agent
type: acp. Around thirty-eight agent harnesses speak the Agent Client
Protocol — Claude Code, Codex, Gemini CLI, goose. Sandcastle now speaks it too.
Point a step at any of them and it becomes a worker in your DAG, with your
gates in front of it and your budget around it.
- id: refactor
type: acp
acp_config:
agent: claude
cwd: /srv/checkouts/api
message: "Refactor the request parser. Keep the tests green."Two things you've never had with an external agent: cancel it gracefully
mid-flight, and watch its tool calls while it works — you see what it's
touching as it touches it, not in a transcript afterwards.
It ships off by default. You name the directories an agent may enter, or the
step doesn't run. Somebody else's agent with write access is a decision, not a
default.
Know the economics before you budget: an ACP turn carries the harness's whole
system prompt. We measured a real one — $0.27 for a one-word answer. Use
timeout as your hard limit on these steps, and let Sandcastle bill what the
harness reports rather than guessing.
Memory an auditor can read — and a grade to prove it
MEMORY_BACKEND=filesystem. Agent memory as markdown: an index, domain
files, an attic for superseded facts, a ledger of what was forgotten and why.
Git-tracked, with every commit pinned into the audit chain. Zero new
dependencies — no vector database to run, nothing to operate. When a
regulator, a customer, or you at 2 a.m. asks "what does this agent actually
remember?", the answer is a folder you can open.
And because storing isn't remembering, there's now a grade:
sandcastle memory eval scores the store itself. Staleness — including the
immortal memories: facts so often confirmed that the store will never
re-examine them, which is exactly how yesterday's truth becomes forever's.
Forgetting health — a memory that only grows isn't a memory, it's a hoard.
Contradiction pressure. And retrieval sanity: whether a query surfaces the
current fact or the version you already replaced.
Every score is arithmetic you can recompute from its own printed parts. No
vibes, no composite magic number.
The claim gets checked
sandcastle audit silent-success. The most expensive failure in production
agents isn't the red run — you see those. It's the green one: "1 reply
created," and nothing was ever sent.
Sandcastle keeps three independent records of what happened — the effect
ledger, the audit chain, the step rows. The new sweep cross-examines them: a
step claiming delivery with no committed effect behind it, a verdict with no
audit event, a completion with no proof. Findings say "claim lacks evidence" —
a report you can act on, tuned hard against false alarms, never an auto-repair
acting on a guess.
Green checkmarks you can interrogate. That's the feature.
Six templates that do knowledge work
The fastest-growing agent workloads aren't in the terminal — legal review,
recruiting, CRM, patient intake. Six new bundled templates put the whole
release to work:
- Contract review — extraction judged by a two-model panel, free checks
first, low-confidence routed to a named human - Recruiting screen — protected attributes stripped in code before any
model sees the file; every claim must quote the CV; human sign-off on both
outcomes - Patient intake — PHI minimised deterministically, clinician approval
gates, nothing leaves without sign-off - CRM enrichment, sales-call brief (with graded memory), marketing
localization QA
Each one demonstrates the pattern the whole release teaches: models draft,
deterministic code checks, judges verify, humans decide the irreversible.
Upgrading
Four things to check. Each takes a minute.
- Gates that filter need one line. A gate whose rejection is routine — "no
material deals today" — should sayfail_on_reject: false. Gates that
guard: change nothing, they finally work the way they read. - Read verdicts from
.error. A failed step publishes no output, so
branch-on-verdict workflows should usefail_on_reject: falseand read the
output as before. MEMORY_BACKENDis honoured now. If you set it to something other than
local, confirm you meant it.- Migrations
022and023run before workers restart. The deploy order
matters and the workers will tell you if you skip it.
Also in 0.47
- Condition steps validate their branch keys — a router that routes nothing is
now a parse error, not a surprise. - Memory reads speak both mem0 API generations.
- The pre-run cost estimator covers
acpandaccept. - The workflow builder knows both new step types.
Full changelog: CHANGELOG.md