Iāve been working on Agent Identity lately.
My mental model started out pretty simple: to send an agent off to do one specific thing, you need answers to at least these questions:
- Which agent / workload is this?
- Who does it represent right now?
- What did that person actually authorize it to do?
- When does that authorization expire?
- Is this particular tool call allowed?
So I spent a while building that whole call path out: the credential can be verified, the delegation chain can be walked, the scope can be checked, the expiry can be checked, and authorization runs again before every single tool call. Different refusal reasons stay distinguishable too.
As the flow came together, my test cases piled up, and in the end I just had Claude fill them out to fifty-odd. All green, no surprise there (ha). I was honestly pretty pleased with myself. Then during code review I accidentally deleted the line that calls authorization. Ran the tests again. Still all green. I sat there for a second: crap, the tests are garbage.
But the more I thought about it, the less that held up. If this were an ordinary library, sure, you could call it a test coverage problem. You ship an authorize(), the application developer forgets to call it, thatās an integration bug.
Except what I was building isnāt a use-it-if-you-feel-like-it helper. Itās a security boundary the agent is not, in theory, supposed to be able to get around.
If application code can delete that one line and the agent still calls the tool, what is all that beautiful authorization actually worth?
Thatās the first time I got genuinely stuck. I had been framing the problem as:
Whatās still missing from identity?
And the question suddenly became:
Who guarantees identity gets enforced at all?
Those are completely different questions.
I had runtime wrong
When I used to see the term āAgent Runtimeā, honestly, it didnāt land. The runtime in my head was closer to:
āthe thing that runs the agent.ā
LangGraph, some SDK, a graph executor, a planner loop, roughly that category. So I thought of runtime as a framework-side concern. Identity was the security feature. Build it properly, wire it in, done.
But the moment I pulled the authorization call out and the tests stayed green, I thought for the first time that the model might be wrong at the root. Because if a security check can be selectively bypassed by application code, it isnāt a boundary, itās an API.
This reminded me of a lot of my platform work. SELinux matters, and not because it has a policy file. Android permissions matter, and not because thereās a permission table somewhere in the framework.
What actually matters is this:
the last path to the resource cannot get around enforcement.
If an app can say:
Iād rather not go through this permission check today.
then thereās nothing left to discuss. So I went back and started checking my own work with one question:
Pull this security check out. Can the system still reach the tool normally?
If it can, the boundary isnāt finished. Iāve built a library.
Then I found the front door had no lock
The funnier part is that I hadnāt finished patching the first hole before I saw the second. All my checks were answering:
Which workload is this?
Is the credential it presented valid?
Does it hold a delegation from Alice?
Is this action inside the scope?
Looks complete. But then I went back and asked something extremely basic:
Hang on, who exactly is connecting right now?
And I couldnāt answer it. Say Alice tells the agent in Slack:
Restart all of device group A for me.
What I had drawn in my head was this:
Alice -> Agent -> Tool
That flow looks reasonable. Except it quietly hides two completely different things:
The first:
Is the person talking to me right now actually Alice?
The second:
Did Alice authorize this agent to do this?
Before I actually started building agent identity, I drew those two as one line. Because delegation can be done very rigorously. The document can say:
delegator = Alice
actor = Agent A
action = restart
resource = group_A
expires = 16:00
Check every field and they all come back correct. But if the name āAliceā came from a session, from conversation state, or from anywhere a model can touch in the first place, then all the authorization downstream is very strictly verifying a name that might be fake. This is where a few things have to come apart:
1. Which workload identity is running this code right now?
2. Which user is making this request right now?
3. Did that user delegate the authority this call needs?
4. Can this runtime / agent workload use that delegation for this action?
These four answer different layers:
- SPIFFE / SVID helps me answer the first.
- OAuth / user authentication handles the second.
- A delegation record handles the third.
- Authorization policy handles the fourth.
Before I got into identity, I couldnāt quite tell these apart:
SPIFFE or OAuth Token Exchange?
Now I understand theyāre answering questions at different boundaries.
The problem I actually hit wasnāt āhow to do identityā
It was around here that I slowly realized the problem Iād hit wasnāt:
How should Agent Identity be designed?
but:
Where do identity / delegation / authorization actually get enforced?
Thatās where I started rethinking runtime. Although honestly, every company is currently using the term a little differently.
Some lean workflow.
Some lean sandbox.
Some count memory in.
Some mean framework + hosting.
Every company defines agent runtime around its own business needs. But from my own experience, thereās one thing Iām now very sure of:
A runtime has to own the execution boundary, at minimum.
Meaning when the agent finally produces a side effect, it has to pass through this layer. For example:
- call API
- restart machine
- modify data
- deploy
- send message
- change config
If the agent application can reach the tool while going around the runtime, then the authorization, sandbox, audit and policy hanging off that runtime are all just optional middleware. That distinction matters far more to me than whether the runtime is built on LangGraph.
And identity ends up somewhere else
My head used to look more like this:
Agent
+-- Planner
+-- Memory
+-- Tools
+-- Identity
Identity as one of the features.
Now I lean toward drawing it like this:
Agent Application
|
| <-- enforcement
v
-------------------------------
RUNTIME BOUNDARY
-------------------------------
User --> 1. Authenticate user
2. Identify workload
3. Validate delegation
4. Authorize action
5. Execute tool
6. Record audit trail
-------------------------------
|
v
Tool
This isnāt saying runtime equals identity. Itās that all of this identity work doesnāt mean much unless itās enforced at the execution boundary. That shift only started getting clear while I was building a Slack bot agent + MCP gateway, because I really did start out treating Agent Identity as a security subsystem. Now I think of it as a set of runtime properties, or more precisely:
security properties the runtime has to enforce.
And then more questions start falling out
After getting this far, I started to understand why this area looks so messy right now. Because once an execution boundary exists, a lot of problems youād normally look at separately suddenly tangle together. Take durable execution: a long-running task has to be able to pick up and finish after an interruption.
Say Alice authorizes the agent at 2pm:
Finish restarting device group A within two hours.
The agent gets halfway at 3pm and saves a checkpoint. At 4pm the machine dies. At 7pm the runtime resumes. Now what? The original delegation expired long ago. You can:
- go get Alice to authorize again
- refresh automatically
- stop and wait for a human
- issue a longer-lived delegation from the start
Those are all possible options. Which made me realize:
durability isnāt simply ācan it resumeā.
It runs straight into authorization lifecycle. And that made one thing very clear:
identity and execution lifecycle donāt come apart.
Then thereās audit, which I canāt leave out either. I used to think about it quite naturally:
the runtime writes an audit log entry every time it takes an action.
Thatās too simple, too naive. If the runtime itself gets compromised, itās also the author of its own history. Thereās no reason to trust that audit log. Same for the sandbox. If the sandbox writes āIām one of the good ones! Trust me! I didnāt do anything badā from inside itself, that sounds a bit off too, right?
So what did I actually learn these past few weeks?
If you only look at the implementation code, what I did this round is Agent Identity.
- credential
- delegation
- authorization
- policy
But if you look at the questions I described, I donāt think the real learning was how to design those primitives. It was:
a security property with no enforcement boundary is just metadata.
A signed delegation doesnāt protect anything on its own. Neither does a beautiful authorization engine. They only start meaning something once the system can guarantee:
every execution with a real side effect has to pass through here
Thatās also why I feel like Iām starting to understand Agent Runtime.
Whatās next
Iām not going to come out and say:
Agent Runtime is X, Y and Z.
This round I only went in through the identity hole. Next I want to keep looking at how durable execution, sandbox, tool boundary and observability actually connect to the runtime, in Temporal, LangGraph, MCP, sandboxes, OpenTelemetry. You can pull plenty of recurring pieces out of those:
- control loop
- checkpoint / resume
- tool boundary
- sandbox
- identity / authorization
- observability
- audit
But the only one of them Iāve dug the hole and fallen into myself is identity / authorization. The rest is still āseen it, read it, thought about itā, not āIāve run itā. So Iād rather not rush to wrap them into a tidy taxonomy. Iāll go into them one at a time.
Happy coding!