Overview
AGENTS.md is useful.
It gives AI coding agents a place to find repo-specific guidance:
how to behave
what conventions matter...
For further actions, you may consider blocking this person and/or reporting abuse
Strong agree on the core, and imo it's the same reason prompt-based guardrails fail: an instruction the agent can choose to ignore isn't a control, it's a suggestion w/ good intentions. Prose can't constrain execution, only the harness can. The model proposes, the code disposes.
Two places I'd push it further though. Declared safe commands only bite if the runner actually enforces the allowlist, i.e. the agent can run the declared tasks and literally nothing else. If it can still shell out to anything and you're just hoping it prefers the safe list, ota.yaml is AGENTS.md w/ nicer syntax, the teeth are in the runner refusing whatever isn't declared, not in the declaration itself. Same logic for receipts: a receipt is only worth something if the harness emits it, not the agent. If the agent writes its own receipt you're back to narration w/ extra steps, since the thing you're verifying is also the thing producing the evidence. Trust comes from the evidence being generated outside the agent's control. Nail those two and the instructions / contract / receipt split is genuinely the right shape.
Yes, fair push.
Ota is stronger than
AGENTS.mdbecause execution is contract-based and receipts are harness-authored, not agent-authored. But you’re right thatsafe_tasksis not yet a full runner-enforced allowlist.Today, Ota can restrict execution to declared contract tasks, and it uses
safe_for_agent/agent.safe_tasksfor visibility, governance, and review. What is still missing is an agent-scoped execution mode where the runner refuses declared tasks outside the safe set.So this is a real product gap, and your framing is the right bar. We’ll prioritize it.
Curious how you enforce that today. Are you using a custom harness, a sandboxed runner, or a tool we should look at?
Honestly it's less a product and more a discipline, I'm not running some slick custom sandbox. The rule I hold is that the agent never sits in the enforcement path, so two things.
First, a capability boundary instead of a preference. The agent only ever gets a fixed set of typed tools, so an undeclared action isn't deprioritized, it just isn't callable, there's no shell to reach for in the first place. Where I do use an agent runner, I lean on the harness being able to hard-deny a call before it executes rather than the model choosing to behave, e.g. Claude Code's permission modes + pre-tool hooks do exactly this, a blocked call is the runner refusing, not the model deciding. That's the closest off-the-shelf thing to what you're describing that I'd point you at.
Second, the receipt has to live one layer down from the thing being judged. For code work that's just CI as the runner, the agent proposes a diff but the gate outside it decides pass/fail and emits the evidence, and it can't merge past a red gate no matter what it thinks it did. I've got a small project (bedrock) built around this, the reliability eval runs in CI against a known-good key and fails the build, so the agent can't author its own green check, the harness does. The second the agent can write the receipt or reach past its tool set you're back to narration w/ extra steps, so the whole game is keeping the thing that verifies separate from the thing that acts. safe_tasks going runner-enforced is basically that, and imo it's the right thing to prioritize.
That makes sense, but it also shows why discipline alone feels transitional to me.
If the boundary lives in operator habit, local harness setup, or “we know not to give the agent a shell,” it can work for one careful team, but it gets harder to scale cleanly across repos, teams, and orgs. What do you think?`
The thing I keep coming back to is: whose discipline is the control once this spreads? The individual operator, the team, platform engineering, or security? And how do you keep that boundary consistent when different teams use different agents and runners?
That is the part we want Ota to handle better: declare the allowed execution surface in the repo contract, let the runner enforce it, and keep the receipt and evidence outside the agent.
Curious how you think about that scaling problem today.
Yeah, I'll concede the framing, discipline as the control doesn't scale, and honestly it's the same critique I'd make of my own answer. "We know not to give the agent a shell" is just a prompt guardrail wearing an ops hat. So declaring the surface in the repo and having a runner enforce it is the right direction, no argument there.
Where I'd push is on where the teeth actually live once it spreads, because I don't think a repo contract plus a runner fully closes it either. The runner is per-dev and opt-in, so the moment one team points a different agent at the repo, or just runs the thing outside Ota, the contract is back to being a suggestion for them. You've moved the boundary from operator habit to runner adoption, which is genuinely better, but it's still a boundary someone can route around by not using the runner. So to me the durable version is the contract compiling down to enforcement at the points that are already mandatory and agent-agnostic across an org: CI required checks and branch protection on the merge side, and the sandbox plus capability and egress boundary on the execution side. Those don't care which agent or runner you used, they sit at a chokepoint nobody opts out of because it's the same gate human PRs already go through.
So I'd frame Ota's contract as the spec, the single declared source of what's allowed, and then the scaling answer is less "everyone adopts the same runner" and more "that spec is enforced at the org chokepoints that already exist and are already non-optional." The local runner enforcing it is great for fast feedback, but imo that's the best-effort layer, not the teeth. Whose discipline is the control? Ideally nobody's, it's the merge gate and the sandbox, same as it already is for the humans.
That’s a strong point, and I think it pushes Ota in the right direction. I appreciate the feedback there.
I agree the local runner is not the final teeth if using it is still optional. That makes it the fast-feedback layer, not the durable control.
The stronger shape is:
ota.yamlas the declared specThat feels like the real scaling path, because it does not depend on everyone using the same agent or even the same runner. The contract stays the source of truth, but the enforcement lives at the chokepoints teams already cannot opt out of.
Curious where you’d start first if you were building that out: compile the contract into CI required checks, or into sandbox/capability policy for the runner?