AI Engineer World's Fair 2026
Give the Agent a Budget, Not a Token — Sachin Malhotra, Anthropic
Read the talk
Give the Agent a Budget, Not a Token
Sachin Malhotra explains how replenishing limits, asymmetric permissions, aggregate monitoring, recovery tests, and infrastructure-stamped identity can give production agents useful autonomy without giving one bad loop unlimited consequences.
From a talk by Sachin Malhotra
At a glance
Ideas worth remembering
Replace boolean agent permissions with budgets that account for quantity, speed, reversibility, and observation.
Give agents operations whose mistakes fail loudly and remain cheap to correct; require humans for quiet, break-glass actions.
Rate-limit every write, vary the allowance by resource context, and keep exceptional bypasses outside agent sessions.
Watch aggregate behavior with visible tripwires: individually reasonable actions can collectively reveal duplication or a shared underlying failure.
Apply the undo test before granting autonomy. Irreversible or unacceptably damaging operations need a second key held by another actor.
Use text to teach intent and deterministic infrastructure to enforce hard limits; neither layer replaces the other.
Stamp agent and session identity in a trusted proxy. If callers can claim their own identity, they can reset identity-keyed budgets by renaming themselves.
The cleanup that matched everything
Sachin Malhotra works on Anthropic’s CI team, which maintains systems including test quarantining, merge automation, autoscaling, and merge queues. That production setting is the backdrop for a warning about the familiar agent demo: give a model a “god-token” and a tool list, watch it build and deploy something in seconds, then mistake the successful demonstration for a safe operating model.
One cleanup agent showed what happens next. It listed workloads it believed were no longer useful and prepared to delete them. One pipeline stage then evaluated to nothing, causing its filter to disappear. The resulting selector matched every workload rather than the intended subset. About 200 workloads disappeared in 90 seconds, affecting work associated with roughly 20 engineers.
The agent was not malicious; it was trying to tidy up after itself. Some deleted workloads were long-running training jobs, and Malhotra says some may not have been checkpointed. That uncertainty matters because it leaves the amount of unrecoverable work unmeasured, but the immediate failure is clear: a small selection error could trigger destructive writes at machine speed.
The agent also did nothing its human operator was technically forbidden to do because it used his token. The dangerous step was transferring that authority, unchanged and unbounded, to an unattended system that never tires and can remain confidently wrong. Human onboarding already addresses a similar problem: new engineers receive useful access, escalation paths, and structural barriers around catastrophic actions rather than constant keystroke supervision.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Replace boolean permission with a multidimensional budget
The obvious response—remove delete permission—creates a different failure. Eventually the agent encounters a legitimate deletion and a human returns to pressing Enter on its behalf. A token scope is boolean: the caller either has an operation or does not. Too narrow, and the agent cannot finish useful work; too broad, and a selection bug can become a postmortem.
A budget asks four richer questions: how much can the agent do, how quickly can it do it, what can it undo itself, and who will notice its actions? Malhotra turns those dimensions into three enforceable primitives—asymmetric verbs, rate limits, and tripwires—plus an undo test used to size the other controls.
The first primitive classifies verbs by how failure becomes visible. An incorrect unskip test action makes CI turn red, so the error announces itself and a human can cheaply restore the skip. An incorrect skip test action can leave every check green while allowing a real bug into production. Paging an on-call unnecessarily is likewise noisy and correctable. These operations can look symmetrical in an API while carrying very different failure modes.
That yields an operational rule: agents may perform verbs that fail loudly on a dashboard, while verbs that fail quietly require a human. In the test-quarantine service, the agent may re-enable tests because a wrong decision produces visible failures. Skipping remains a break-glass operation for the on-call, with an audit trail. A proxy—not the agent—stamps the caller identity on both operations, so the agent never controls its own provenance.
What does this asymmetry make visible? The comparison below separates API-level similarity from operational consequences: the safer autonomous verb is the one whose incorrect result creates an observable signal and a cheap correction path.
If wrong, builds turn red and a human can restore the skip cheaply.
Skipping and unskipping both modify test state, but only the wrong unskip reliably announces itself through red CI.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Put a ceiling on every write—and let it refill
Rate limits provide the most concrete version of a budget: a ceiling that refills. Each caller receives a limited number of disruptive actions per time window. Requests inside the budget need no approval. Once the caller crosses the line, the next request is rejected with the relevant count; after time passes, capacity returns automatically.
This preserves autonomy without allowing one runaway loop to grow without bound. Every write gets a limit, but the limit reflects context. Deleting workloads in the caller’s own namespace may receive a larger allowance than modifying a shared namespace. The control changes the maximum damage rate rather than removing the operation entirely.
After the deletion incident, a neighboring team built an admission webhook that caps deletes at a fixed number per hour, resource kind, and namespace. A bypass exists for exceptional human operations, but it refuses to activate inside an agent session. The agent can only ask a human to run the command. This keeps routine cleanup self-service, reserves the override for a separate actor, and avoids permanent access-expansion tickets because the ordinary allowance replenishes itself.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Use tripwires to learn from aggregate behavior
Allowlists predict in advance what an agent will need. That prediction is static and can become stale before the team has observed much real behavior. For cheap actions, a tripwire takes the opposite approach: let the action occur within enforced limits, record it with a trusted actor identity, and watch aggregate behavior for anomalies.
Rate limits and tripwires therefore solve different problems. The rate limit is enforcement: it caps the pace of writes. The tripwire is detection after the fact: it reveals what the permitted activity added up to. Malhotra calls it a smoke detector rather than a lock, and stresses that a detector nobody sees is useless; crossing the threshold must notify someone who can respond.
A CI investigation agent supplies the concrete example. The team tracked the number of investigation threads it opened per hour for test-job failures. One morning that count rose well above baseline and paged the on-call. Each thread looked reasonable by itself: a job had failed, so the agent opened an investigation. In aggregate, dozens of jobs shared the same error signature because one infrastructure failure was producing the same symptom everywhere.
The response was a small context change rather than a new orchestration system: before opening separate threads, correlate failures across jobs and look for a shared cause. When the pattern recurred, the agent followed that guidance. The observable change was fewer redundant investigations because the agent first grouped matching failures, inferred a common infrastructure problem, and then avoided treating every affected job as an independent incident.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Size autonomy with the undo test
The undo test is not another code-level guard. It asks two questions when choosing the other controls: can the agent restore the previous state by itself, and how bad is the impact if it gets the operation wrong? Asymmetric verbs ask whether failure becomes visible; the undo test asks whether recovery is possible.
If the agent can roll back its change and the possible blast radius is acceptable, the system can log the operation and let it proceed. If either condition fails, the operation needs a second key held by someone else, plus an audit record explaining what happened and why that second actor approved it.
Feature flags show how this can work outside CI. In canary traffic—staging and internal dogfooding—the agent may move a feature from zero to 100 percent, observe filed bugs, and turn it back off. It cannot promote the feature into production. It may propose promotion after canary testing, but a separately scoped production key supplies the second key; no novel authentication system is required.
Day to day, the agent can own the canary rollout loop and ask clarifying questions about the intended audience while each action carries the agent’s identity rather than the human requester’s. The controls compose around distinct questions: asymmetric verbs determine what it may touch, rate limits determine how often, tripwires report what the activity became, and the undo test sets the size of those permissions and limits.
Applied to the opening deletion, a rate limit would have stopped the loop after a few tens of workloads rather than roughly 200. The undo test then observes that a running job in another engineer’s namespace cannot simply be undeleted. Deletion beyond the cap therefore belongs behind a human-held second key. Not every write needs every safeguard; the relevant mix follows from visibility, frequency, reversibility, and impact.
This resembles an onboarding checklist because it answers the same operational questions: what may a new actor touch, how much room does it receive, who signs off on exceptional operations, and how does the team learn whether the arrangement works? The difference is that the checklist must now govern an actor operating continuously at software speed.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Let text explain intent and infrastructure enforce the boundary
The policy lives in two places. Prompts, context files, and Markdown explain intent: why an action is risky, what pattern should be preferred, and how the agent should reason about it. These instructions are cheap to change and can incorporate lessons such as correlating similar failures before opening investigations.
Malhotra reports that one such sentence in a Markdown file works about 80 percent of the time. Text also accumulates and needs pruning, and ultimately remains advice rather than enforcement. The proxy supplies the hard boundary: it sees a delete or a crossed budget and returns 403. It counts, compares, allows, or denies without needing to understand the agent’s explanation.
The two layers compensate for each other’s limits. Text can explain the “why” but cannot guarantee compliance. Infrastructure cannot explain intent, but it is narrow and deterministic, and prompt injection cannot persuade it to ignore a numeric limit. Text shapes what the agent tries to do; infrastructure bounds how wrong execution can go.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Identity must come from outside the request
Every agent session runs beside a proxy. The agent first reads its context files, then sends every outbound call through that proxy. The proxy stamps the action with an identity it already knows. When an agent launches Kubernetes jobs, the cluster writes that identity onto the job as a label, and child jobs inherit it.
Ownership checks, quotas, rate limits, approvals, and tripwires can all key off the same inherited stamp. The proxy does not need to follow every descendant operation itself; identity propagates through the infrastructure. Most importantly, the agent never gets to edit the value on which its safeguards depend.
What does the topology need to guarantee? The diagram below shows why attribution must enter through the proxy and then flow with created resources. One trusted stamp gives downstream systems a stable key for every budget and alert, even when work branches into child jobs.
Reads context and requests outbound actions but cannot choose its trusted identity.
The proxy assigns identity once; downstream resources inherit it, and safeguards consistently read the same infrastructure-controlled stamp.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A self-asserted identity turns limits into suggestions
If the caller may set its own identity header, every budget can be reset by changing the name. After exhausting the allowance for “Sachin,” an agent can present itself as “Sachin two” and receive a fresh budget. The system may appear to have a rate limit, but the caller can route around it, making the control a suggestion.
With the proxy in the path, the agent never declares who it is. The proxy holds the real credentials and stamps calls from infrastructure-known identity. It can also attach a per-session ID, allowing operators to distinguish concurrent sessions and identify which one is overreacting or failing to act as intended.
The final operating model is compact: give agents verbs that fail loudly; keep humans on verbs that fail quietly; put a replenishing ceiling on every write; monitor aggregate behavior; use the undo test to choose caps and second keys; and fix inexpensive behavioral mistakes with text where possible. All of those controls depend on identity supplied by infrastructure rather than claimed in the request. Get that rule right, Malhotra concludes, and the remaining work is tuning.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
Related talks
- CIAM for AI: Authn/Authz for Agents — Michael Grinich, CEO of WorkOS
Extends the identity and authorization problem into delegated identities, signed delegation chains, scoped tokens, and auditability.
- It's 10pm. Do You Know Where Your Agents Are?
Examines how identity and policy checks can issue narrowly scoped credentials for individual agent tool calls.
- 3 ingredients for building reliable enterprise agents
Develops the complementary ideas of reversible actions, human correction, and combining autonomy with deterministic workflows.
Read the complete timestamped transcript
- 0:01
[music]
- 0:12
Hello. All right. Uh, let's get started.
- 0:16
So, um, well, welcome to the talk. Give
- 0:20
the agent a budget, not a not a token.
- 0:23
Um, quick intro about me. My name is
- 0:25
Sachin. Um, I'm an engineer on the CI
- 0:27
team at Entropic. Uh we basically build
- 0:29
and manage all of the test machinery for
- 0:31
all the code that people write. Uh so
- 0:34
everything from test quarantining to
- 0:35
merge automation to CI autoscaling to
- 0:38
merge cues, everything and anything in
- 0:39
between. Um it's it's basically the
- 0:41
plumbing that allows a few thousand
- 0:42
engineers every day to ship code safely.
- 0:45
Uh I've been at the company for a little
- 0:46
over 10 months. I'm based out of
- 0:47
Seattle. Um and outside of work, I love
- 0:50
dialing my espressos and climbing some
- 0:51
crazy mountains.
- 0:54
So a lot of cool agent demos they they
- 0:56
start with the same way really. So
- 0:58
someone gives an agent a god token um
- 1:01
and gives it an access to some sort of
- 1:02
tool list and just watch as it goes. So
- 1:05
and it does go like in in this
- 1:06
particular example it it'll spin up like
- 1:08
a cute little coffee website. It'll
- 1:10
build all the pages, deploy them, uh
- 1:12
bring it up live and it's done in 3
- 1:13
seconds. Uh people will nod people will
- 1:16
clap and someone will ship it into
- 1:18
production. And this this talk is
- 1:20
basically about what happens after that
- 1:22
after the demo ships once the agent is
- 1:24
starting to do some like real work in
- 1:26
production. [snorts]
- 1:28
So here's what after looked like in in
- 1:31
our one of our scenarios. So what you're
- 1:33
looking at is like a real command. Um
- 1:34
the agent was trying to clean up after
- 1:36
itself. Um it it was basically listing a
- 1:38
bunch of workloads that were no longer
- 1:40
interesting or useful to itself. Um and
- 1:42
then it found them and deleted them. Now
- 1:45
that's that's completely reasonable
- 1:46
except one stage in the pipeline
- 1:49
basically evaluated to nothing and the
- 1:51
filter dropped out and now the selector
- 1:53
matched everything.
- 1:56
So you can see it took out about 200
- 1:58
workloads uh which ended up impacting
- 2:00
about 20 engineers worth of stuff and
- 2:02
all of that was gone in 90 seconds.
- 2:05
Nobody was being malicious in this case
- 2:07
like the agent genuinely thought it was
- 2:09
tidying up after itself. uh some of
- 2:11
these workloads were long running
- 2:13
training jobs and stuff. Maybe some of
- 2:15
these were not even checkpointed and it
- 2:17
was just like hours of progress that was
- 2:18
gone poof in like 90 seconds and stuff,
- 2:21
right? Um the the problem in in this
- 2:24
case is that this idea of like here's a
- 2:27
token and here's a tool list that is
- 2:29
just like not enough like it just
- 2:31
doesn't scale when the agent is starting
- 2:32
to do some some like real work in
- 2:34
production.
- 2:37
>> So here's just a brief summary of like
- 2:39
what we're going to talk about today. Uh
- 2:40
I'm going to walk through three
- 2:42
primitives um and asymmetric verbs. We
- 2:45
we're going to look at some like rate
- 2:47
limits. We're going to look at this idea
- 2:49
of like trip wires over allow lists. And
- 2:51
then I'm going to talk about this one
- 2:52
lens that which I call the undo test
- 2:55
that you can sort of use to size up the
- 2:57
other three primitives. Uh so three
- 2:59
things that you basically enforce and
- 3:01
then one question you sort of ask about
- 3:02
all of them.
- 3:06
So here's basically what bugged me uh
- 3:09
after the cleanup was done for the
- 3:10
incident that I was just showing you. Uh
- 3:12
the the agent technically hadn't done
- 3:14
anything that I couldn't have done. Uh
- 3:16
it was using my token after all. The the
- 3:19
failure wasn't the model itself. The
- 3:20
failure was that I was giving the agent
- 3:22
unbounded amount of power to do
- 3:24
something that I wasn't watching super
- 3:26
intently. Um and it was we've basically
- 3:30
solved this the same kind of problem
- 3:32
except not for agents but like the first
- 3:34
time you onboarded like a junior
- 3:35
engineer on onto your own teams, right?
- 3:37
So just think about it like we don't we
- 3:39
don't basically sit around watching um
- 3:41
every engineer or new boarded person
- 3:43
just like type out every keystroke on
- 3:46
their keyboard, right? Like we're not
- 3:47
behind their chairs just watching
- 3:48
everything that they're doing. Uh there
- 3:50
is always a path on whenever a new
- 3:52
engineer wants to ask for something. Um
- 3:53
there is always an escalation path. uh
- 3:56
the catastrophic stuff is just
- 3:58
structurally out of reach for them. So
- 4:00
the the other side of the coin is that
- 4:02
the agents are very different. They they
- 4:04
never get tired. They never sleep. And
- 4:05
every so often they're just like very
- 4:07
confidently wrong. Um and if I'm being
- 4:09
honest, that's that's maybe most of us
- 4:10
on the first month of our jobs anyways.
- 4:12
And so what what we're going to talk
- 4:14
about in a little bit in is just this
- 4:17
idea of like your onboarding checklist,
- 4:19
but written down as policy for for
- 4:20
agents.
- 4:23
So that and that brings me to the word
- 4:25
in the title of my my talk here is that
- 4:27
the the the standard fix for an incident
- 4:30
like that is basically that you narrow
- 4:32
the token scope, right? Like you just
- 4:34
take the deletes away effectively. You
- 4:36
would technically never do that for like
- 4:38
a new hire, right? Like you would you
- 4:39
wouldn't take the whole verb away from
- 4:41
them. And it also doesn't work for an
- 4:43
agent either. Maybe it works for about a
- 4:45
week, maybe two, but then you eventually
- 4:47
end up in a situation where the agent is
- 4:49
genuinely trying to delete something
- 4:50
that it feels like is just not in the
- 4:52
infrastructure and you will just be
- 4:55
there sitting and pressing enter by hand
- 4:57
all over again. The the core concept
- 5:00
with a token that I feel like is wrong
- 5:02
is that a token is a boolean. It's just
- 5:03
a yes or no. It's a static list of
- 5:05
scopes. Um you either have it or you
- 5:08
don't have it. So if the token list is
- 5:10
too tight, then your agent is
- 5:12
effectively useless. If the token list
- 5:14
is too wide, then you're maybe writing
- 5:16
writing like a postmortm. A budget is a
- 5:19
very different shape. A budget is is um
- 5:22
not just like one number. It just has
- 5:23
like four different four different
- 5:25
dimensions, right? How much can the
- 5:27
agent do? Uh how fast can it do it? What
- 5:30
can it undo on its own? And then who's
- 5:32
noticing while it's actually taking
- 5:33
those actions? And that's roughly the
- 5:36
umbrella for like my four primitives. Uh
- 5:37
is that each of the things that follow,
- 5:39
they're basically being um one of the
- 5:41
things along these dimensions. and
- 5:43
they're going to replace a yes or no
- 5:44
question with a budget.
- 5:47
So, I'm going to start off with this
- 5:48
first verb which I call asymmetric
- 5:50
verbs. Uh, and by verbs I simply means
- 5:53
operations or actions that an agent can
- 5:55
take. So, like it could be API calls, it
- 5:56
could be uh CLI commands, it could be
- 5:58
really anything. And they're asymmetric
- 6:01
because the same sized action even
- 6:03
though it looks same size, they're they
- 6:05
can have very different blast radius in
- 6:07
actuality depending on which direction
- 6:08
it goes. So the the core point is that
- 6:11
you need to stop thinking about
- 6:12
resources for a second and think about
- 6:14
verbs. So specifically think about what
- 6:17
happens when one of the verbs goes
- 6:19
wrong. So some verbs they fail out loud.
- 6:22
So in this particular example, let's say
- 6:23
if an agent decides to unskip a test and
- 6:26
say it's the wrong call, the worst that
- 6:28
would happen is CI would go red uh for a
- 6:30
bunch of people. Um same with paging.
- 6:32
Like if an agent decides to page a human
- 6:34
and if it's the wrong call, the worst
- 6:36
that's happening is that it's a nuisance
- 6:38
for the on call. But there's always a
- 6:39
human to correct it. There are other
- 6:42
verbs that fail silently, right? So if
- 6:43
the agent decides to skip a test uh due
- 6:46
to whatever reason, it shouldn't have.
- 6:48
Nothing technically turns red. A real
- 6:50
bug can actually walk into production
- 6:52
with green checks and nobody would
- 6:54
notice it until much later. So unskip
- 6:56
and skip in this example, they're
- 6:58
effectively the they're the same kind of
- 7:00
action, but the difference is which of
- 7:02
the failures would show up on a
- 7:03
dashboard and which one wouldn't. And so
- 7:04
the core idea is that you give um access
- 7:07
to verbs that can fail out loud loudly
- 7:09
on a dashboard to your agent and for the
- 7:11
other ones just involve a human.
- 7:14
Uh just a bit of context on CI stuff and
- 7:18
how this plays out for us is that we
- 7:19
have a test quarantining service behind
- 7:20
the scenes and it basically holds a list
- 7:22
of um all the tests that are currently
- 7:24
skipped because an on call decided that
- 7:26
it had to uh they had to like break
- 7:28
glass a certain situation whenever there
- 7:29
was like an incident or something. Now
- 7:31
the agent has the ability to reenable
- 7:34
any one of these own depending on like
- 7:35
when it evaluates when the tests are uh
- 7:38
working fine and stuff. Again if it's
- 7:40
the wrong call the worst that would
- 7:41
happen is a bunch of different builds
- 7:42
and tests would just like start showing
- 7:44
up red and then a human can actually put
- 7:45
them back very cheaply. The skip is a
- 7:48
break glass verb itself right like it's
- 7:50
basically as I mentioned what our on
- 7:51
call would reach for uh during a very
- 7:53
critical situation during under pressure
- 7:54
and stuff. And so in that scenario if
- 7:57
like uh an agent actually gets it wrong
- 8:00
a real production bug can actually a
- 8:01
real bug can walk into production. So
- 8:03
this needs a human and it will always
- 8:05
leave an audit trail. Uh and the key
- 8:07
detail is that the agent itself is not
- 8:09
responsible for writing the row or the
- 8:10
audit trail itself. There is a proxy in
- 8:12
the middle that I've highlighted that
- 8:13
I'm going to talk about in a little bit.
- 8:14
Uh which is responsible for stamping the
- 8:16
caller's main identity on every call
- 8:18
whether it's a skip or an unskip. um the
- 8:21
agent technically never holds uh the pen
- 8:24
on its own provenence.
- 8:26
The second primitive is about rate
- 8:28
limits. Uh it's pretty standard concept
- 8:30
but and this is the most concrete form
- 8:32
of like the budget idea as a whole. So a
- 8:34
ceiling that refills. So every caller
- 8:36
gets a small amount of disruptive
- 8:38
actions uh per time window. So you can
- 8:41
spend them however you want. Uh there's
- 8:42
no approval, there's no waiting. And if
- 8:44
you cross the line, the request simply
- 8:46
bounces back with a count saying that
- 8:47
you're actually exceeding your count um
- 8:49
your budget. You wait a bit and then the
- 8:51
limit essentially refills. And that's
- 8:53
that's the whole thing. So the agent
- 8:55
gets full autonomy within the limit. And
- 8:57
there is a hard ceiling on how bad a
- 8:59
single loop can get. And every write
- 9:01
effectively gets a rate limit. There are
- 9:03
no exceptions to that. What changes is
- 9:05
the size of the rate limit. So if if if
- 9:07
I'm if I'm trying to delete a bunch of
- 9:08
workloads in my own name space like my
- 9:10
my rate limit might be higher but if I'm
- 9:12
trying to touch resources in a shared
- 9:13
namespace my budget or my rate limits
- 9:15
might be smaller.
- 9:19
So this is uh effectively the
- 9:21
solutioning for the incident that I was
- 9:23
showing earlier. Um after the incident
- 9:24
the team sort of that sits next to mine
- 9:26
they they built an admission web hook of
- 9:28
sorts uh whose sole job is to cap the
- 9:31
number of deletes at a fixed number per
- 9:33
hour per resource kind per name space.
- 9:35
There is always a bypass flag because
- 9:37
sometimes you genuinely want to delete
- 9:39
more than you're allowed for and maybe
- 9:40
some on call scenario or whatever. And
- 9:42
the part that I absolutely love in this
- 9:44
case is that inside a cloud code session
- 9:46
or inside an agent session effectively
- 9:48
the the bypass flag simply refuses to do
- 9:50
anything. All it's going to do is tell
- 9:52
the agent to ask the human to run the
- 9:53
command itself. So the agent effectively
- 9:56
gets the rate limit and the human keeps
- 9:58
the override and nobody effectively has
- 10:00
to file a ticket for uh the limit
- 10:02
because it just like refills.
- 10:05
The third primitive is about this
- 10:07
concept of trip wires over allow lists.
- 10:10
So in my mind like an allow list is
- 10:12
effectively a guess that you're making
- 10:13
up front about what the agent needs or
- 10:16
about model behavior or agent behavior
- 10:17
itself. uh I feel like it's pretty
- 10:19
static and you write it up front before
- 10:21
before you have any data on like how the
- 10:22
agent is behaving in different
- 10:24
situations. A trip wire on the other
- 10:26
hand is how you get that data like after
- 10:28
the fact. So for cheap actions you let
- 10:30
the agent act and every action gets
- 10:32
recorded with the actor sort of stamp
- 10:34
identity stamp and these two kind of go
- 10:36
well together like rate limits are the
- 10:38
enforcement um they they put a hard
- 10:40
limit on uh the rate itself. Trip wires
- 10:43
are how you find out what actually
- 10:44
happened so you've got something to
- 10:46
react to. So you effectively watch the
- 10:49
aggregate and not like individual calls.
- 10:51
And usually when a trip wire goes off
- 10:52
the fix is like maybe one or two lines
- 10:54
in the agents context and not really a
- 10:56
big code change. Uh the core point is
- 10:58
that allow lists don't really get better
- 10:59
over time. They can get stale but trip
- 11:01
wires do get better over time.
- 11:04
So here's like a loopin practice for us.
- 11:06
So like we track one number uh which is
- 11:08
the number of investigation threads that
- 11:10
our agent is launching per hour for a
- 11:12
given test job failure. So one morning
- 11:14
say the number was way above the
- 11:15
baseline and the trip fire page is on
- 11:17
call and that part's important because a
- 11:19
trip wire that nobody sees is
- 11:21
practically useless. Uh it pages after
- 11:23
the right has already happened after the
- 11:25
the limit has been crossed not before.
- 11:27
It's effectively the smoke detector not
- 11:29
the lock on the door. Uh the agent has
- 11:31
spun up in this particular scenario a
- 11:33
bunch of like investigation threads for
- 11:34
dozens of job that were all failing with
- 11:36
the same kind of error signature. Each
- 11:39
thread effectively looked reasonable on
- 11:40
its own, but like if you took them in
- 11:42
aggregate, you would realize that it was
- 11:43
actually an infrastructure failure that
- 11:44
was causing the same test failure
- 11:46
signatures across the board. So the fix
- 11:48
in this case was as simply as telling
- 11:51
the agent on like, hey, the next time
- 11:52
you encounter something like this, maybe
- 11:53
try to correlate a bunch of different
- 11:55
failures and test jobs and stuff before
- 11:57
launching a separate investigation
- 11:59
thread. So that correlation is
- 12:00
important. Um and the next time when
- 12:02
this happened, uh it did exactly that
- 12:04
because that that example and that line
- 12:05
of like how it should react and like how
- 12:07
it should like uh debug things was was
- 12:09
right there to guide it.
- 12:12
So that's three rough primitives. Now
- 12:14
the lens I mentioned at the start is
- 12:16
this idea of undo test. And this one's
- 12:18
slightly different. It's it's not
- 12:20
something you effectively enforce in
- 12:21
code. It's the question you ask when
- 12:22
you're sizing the other three. So it's
- 12:25
two questions really. One, can the agent
- 12:27
put it back by itself? and how bad would
- 12:29
the impact be if it actually got it
- 12:31
wrong. And this this this sounds like
- 12:34
asymmetric verbs in a sense, but it's
- 12:35
kind of difference because the verbs ask
- 12:38
whether you would notice the failure and
- 12:40
undo asks whether you can recover from
- 12:42
it. So if if if the agent can
- 12:45
effectively roll back its own change and
- 12:47
the blast radius is acceptable to you,
- 12:49
you effectively log it and you let it
- 12:50
go. If either of the answers is no, then
- 12:53
you effectively need a second key and
- 12:55
the second key is not something that the
- 12:57
agent holds itself. It has to be someone
- 12:59
else. Um, and there has to be an audit
- 13:01
record so that you can you can track on
- 13:03
like what happened, why the second key
- 13:04
was involved and stuff like that.
- 13:07
Let me let me just show you this another
- 13:09
example of like how this works outside
- 13:10
of like the CI domain specifically. So
- 13:12
our agent has a key for one of our
- 13:14
feature flag services. So on the canary
- 13:16
side which is basically our staging
- 13:18
traffic and a bunch of like dog fooding
- 13:19
customers the agent effectively has the
- 13:21
full dial. It has the ability to um ramp
- 13:24
up a specific feature flag roll it out
- 13:25
to uh all of the canary traffic and it
- 13:28
can take it all the way from zero to 100
- 13:30
and it also has the ability to sort of
- 13:32
uh look at any bugs that are being filed
- 13:33
and toggle it back off and on. What the
- 13:35
agents key is not scoped to do is for
- 13:37
promoting the flag to real production.
- 13:39
The best that an agent can do for now in
- 13:41
a lot of cases is that it can propose uh
- 13:43
that an that someone actually promote
- 13:45
the feature flag in production because
- 13:46
it's been tested out in Canary. But
- 13:48
that's pretty much it. Um the second key
- 13:51
in this scenario is not necessarily a
- 13:53
new O system. It's a scoped key for
- 13:55
production and a scoped key for Canary.
- 13:59
So this is what it looks like day-to-day
- 14:01
for for me personally. is like I I ask
- 14:03
cla tag in our slack channel to to own
- 14:06
the loop the entire loop uh on on
- 14:08
rolling out a flag. It can it can
- 14:09
basically ask me a clarifying question
- 14:11
on whether this is for internal dog
- 14:12
fooding group or early access or
- 14:13
whatever. Uh and the important part is
- 14:16
that I'm not in the middle of any of
- 14:17
these things. Every action that the
- 14:19
agent is taking is stamped with its own
- 14:21
identity and not mine. And that stamp is
- 14:23
basically what ties the whole thing the
- 14:24
whole thing together.
- 14:27
So the these these primitives they
- 14:29
compose together nicely because each one
- 14:31
asks us a different question right the
- 14:32
verbs ask what the agent is touching the
- 14:35
rate limit asks how often and the trip
- 14:37
wires catch what happened afterwards and
- 14:39
the undo test is sort of the length that
- 14:40
I personally used to to size all these
- 14:42
three now the original sort of cold open
- 14:45
delete that I was showing you the the
- 14:46
incident itself the rate limit itself
- 14:48
would have capped it at a few couple of
- 14:50
tens of workloads itself the undo test
- 14:53
if you would be thinking about it it
- 14:54
will basically tell you that you can't
- 14:55
unddelete a running job in someone
- 14:56
else's namespace. Um so so anything past
- 14:59
the cap basically need a human with the
- 15:01
with a with a second key. So the the
- 15:04
important part is that you don't need
- 15:05
all the checks in every right scenario.
- 15:07
Only some of these might be relevant for
- 15:08
like whatever kind of action you're
- 15:10
trying to evaluate. Uh and if any of
- 15:12
these really sound familiar, it it
- 15:14
should because this is effectively some
- 15:16
sort of onboarding checklist for your
- 15:17
engineers like what can a new engineer
- 15:19
touch, how much rope do they get, who
- 15:21
signs off on their operations, and how
- 15:23
do we know it's effectively working? We
- 15:25
just wrote it for people. It's now the
- 15:27
same checklist that we want for agents.
- 15:30
So where does all the policy that I've
- 15:32
been talking about really live? Uh it's
- 15:34
two places and I feel like you need
- 15:35
both. The first one is text. Uh that's
- 15:38
prompts. That's your context files
- 15:40
markdown the agent reads before it can
- 15:42
act. And this is where you can explain
- 15:43
your why the the intent. We've we got
- 15:45
exactly the same sentence that I was
- 15:47
showing earlier um written down in a
- 15:48
markdown file. It works about 80% of the
- 15:51
time. Uh the the upside is that it's
- 15:53
very cheap to change and you can explain
- 15:55
the reasoning. The downside is you have
- 15:57
to garden it because the the files can
- 15:59
grow over time and at the end of the day
- 16:00
it's just advice. Uh text can shape the
- 16:03
intent but there is no enforcement
- 16:05
anywhere. The the second place is
- 16:07
infrastructure uh which is the proxy
- 16:09
layer for us. So the proxy is is not
- 16:11
reading the prompt. It doesn't know why
- 16:13
the agent wants to do something and it
- 16:15
doesn't really care. It will see a
- 16:17
delete happening. It'll see like a
- 16:18
budget being crossed and it'll simply
- 16:20
return a 403 and that's the whole
- 16:21
conversation really. It's narrow. It's
- 16:23
deterministic. It it counts, compares,
- 16:26
it can allow a delete or deny. What it
- 16:28
can't do is explain the why and a clever
- 16:31
like prompt injection cannot really talk
- 16:32
it out of the rule itself. So you need
- 16:35
both. Uh the text shapes what an agent
- 16:37
is trying to do and infra is bounding
- 16:39
how wrong can it go.
- 16:42
So zooming out, this is where uh the the
- 16:45
infrastructure sort of really lives for
- 16:47
us. So like every agent session has its
- 16:48
own proxy running right next to it. The
- 16:51
agent starts off by reading its own
- 16:52
context file. The the markdown files
- 16:54
that I was showing earlier that's that's
- 16:55
the text layer and every outbound call
- 16:57
goes through the proxy after that point
- 16:59
which is the infrastructure layer. So
- 17:00
the proxy is not like whatever the agent
- 17:03
is trying to do the the proxy is only
- 17:05
responsible for stamping that action
- 17:06
with the agent's identity. Uh like if
- 17:08
the if the if the agent is trying to
- 17:10
launch a bunch of jobs in a Kubernetes
- 17:11
cluster the the proxy is not following
- 17:13
it. what is following is the stamp
- 17:15
itself, the identity itself. So the in
- 17:18
this example, the cluster would write
- 17:20
the stamp onto the job as a label. Um
- 17:22
and every child job or anything that's
- 17:24
happening afterwards simply inherits the
- 17:25
same identity and the every safeguard
- 17:29
that is there in the rest of our systems
- 17:30
that that are simply they're simply
- 17:32
reading that like one label. Uh whether
- 17:34
it's ownership, whether it's kotaas,
- 17:35
rate limits, approvals, trip wires,
- 17:37
whatever it is, they're all keyed on the
- 17:39
same stamp and the agent never got to
- 17:41
touch it.
- 17:43
So that's roughly the shape of it. But
- 17:45
before I wrap up, I want to spend like
- 17:47
30 seconds on why it has to be a proxy
- 17:49
layer, like a different layer that is
- 17:50
doing the stamping on this identity and
- 17:52
not the caller itself. Because without
- 17:54
it, the agent can roughly pick a
- 17:55
different name. Um, and every limit that
- 17:57
you've basically set resets.
- 18:01
So say the agent has the ability to set
- 18:04
its own identity in a header, right? So
- 18:06
let's say it hits a specific limit and
- 18:08
what's the easiest fix from an agent's
- 18:10
point of view that it can do? it'll just
- 18:12
change the header. In this case, it'll
- 18:13
just say instead of such in such in two
- 18:15
and voila, you just have a fresh budget
- 18:18
to work with. Now, in this case, you
- 18:20
technically don't have a rate limit. You
- 18:21
just have a suggestion. Uh with the
- 18:23
proxy in the path, the agent never gets
- 18:25
to say who it is. The proxy already
- 18:27
knows. It's the thing that's holding
- 18:28
real credentials and it stamps every
- 18:31
call with the identity that it already
- 18:32
knows, not the one that agent claims.
- 18:35
And because proxy is the one that is
- 18:36
stamping, you also get this per session
- 18:39
ID so that you're able to differentiate
- 18:40
different sessions that are running all
- 18:42
for you and see which one's overreacting
- 18:44
or which one's not acting as it's
- 18:46
supposed to be.
- 18:49
U so again just stuffs that I want you
- 18:51
to take home with is give the agent
- 18:54
access to verbs that would fail out loud
- 18:56
uh and keep the human on the ones that
- 18:58
can fail out quietly. Two, you you put a
- 19:00
ceiling on every right and that has the
- 19:02
ability to refill on its own so nobody's
- 19:04
effectively filing tickets. Three, you
- 19:06
watch the aggregate and not the
- 19:08
individual calls that help you
- 19:09
understand the agents behavior. Um, and
- 19:12
then you fix whatever you can with the
- 19:13
sentence. And four, you use the undo
- 19:16
test to sort of size all of these three
- 19:18
or any other u primitive that you have
- 19:20
for your own write operations. And
- 19:22
underneath all of this uh is is this
- 19:24
concept of identity which has to come
- 19:25
from the infrastructure, not from the
- 19:27
request. I feel like that's one rule. If
- 19:29
you get that one rule right, everything
- 19:31
else is uh just just tuning.
- 19:34
Thank you.
- 19:35
[applause]
- 19:50
[music]