All lessons › Function E — The Agentic SOC › Understand — Correlation, Intel and the Hunt
E3.4

When the actor is an agent — three instincts that misfire

E3
▶
Lightboard recording

Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.

Video placeholderpublishes automatically from recordings/E3.4.mp4
Risk

"Which user" is now the wrong first question.

Control

Attribute to agent, authority, delegation chain and prompt.

The lab

Attribute an incident through the B2 act chain.

◉Use case relevance

The internal actor was autonomous. Was it instructed, was it compromised, or did it simply do what it was allowed to do? None of your existing playbooks have a branch for that question, and the answer changes everything downstream.

At CyberTravels. Three instincts, each correct for a person and confidently wrong for an agent. Run attribute() on a row whose chain reads priya => spiffe://… and it answers all four questions; run it on service-account — the estate before B2.x — and it answers one, naming the other three as gaps rather than guessing them.

◴What this lesson is — Day 0, Day 1, Day 2

The three responder instincts that are correct for a person and wrong for an agent, and the four questions that replace 'which user' — with the record answering them or naming which it cannot.

Day 0 — why

Three responder instincts that are right for people misfire on agents, and each one burns the clock.

Day 1 — how

Revoke the agent identity rather than disabling the account, read the plan rather than interviewing the user, and assume a chain rather than an actor.

Day 2 — measure

Time lost to each misfire, and whether the bearer token was still valid after the account was disabled.

Measure this

what to measuredenominator or target
time lost to each misfireminutes
whether the bearer token was still valid after the account was disabledyes/no

▦The framework, and how it works

   the internal actor was autonomous. which branch?

   instructed      someone told it to        -> who, and through what channel
   injected        content told it to        -> which corpus, written by whom
   permitted       it was allowed to         -> a control gap, not an intrusion

   no existing playbook has this branch, and it changes everything after it

Three responder instincts are correct for human incidents and misfire when the actor is an agent.

  1. Disable the account. For a human this stops them. For an agent holding an already-issued bearer token, it may not — the token remains valid until it expires.
  2. Interview the user. They were asleep. They authorised a task; a model chose the actions. They cannot tell you what happened.
  3. Assume one actor. There were three, in a chain, and only the last one touched the resource.

The correct first action is to revoke the agent identity, which is only possible if B2 was done. This lesson is where the identity track's value becomes operational rather than architectural.

Anchor → E1.0. Three responder instincts each burn the interval: disabling an account that does not stop an already-issued bearer token, interviewing a person who was asleep, and assuming one actor when there were three in a chain.

2 · Demo — the three instincts, tested

3 · The control — revoke the agent identity first

the runbook you havethe runbook this incident needs
1. disable the user account1. identify the acting identity from the act chain (B2.5)
2. interview the user2. revoke that identity — no approval needed for a non-human (B3.6)
3. review the user's recent activity3. scope by walking the delegation chain, not the host list (E3.7)
4. preserve the run trace before anything restarts (E5.1)
5. only then consider the human's account, and say why
Every step on the left is correct for a human actor and wrong here. The human authorised a task; the actions were chosen by a model.

4 · The procedure, as a skill

Disabling the human's account leaves both agents acting on tokens already issued. The skill enumerates the live sessions, simulates the reflex containment step, and separates the task the user authorised from the actions taken under it.

▶Real time execution as skill

The skill — skills/response/agent-actor-containment/SKILL.md

name: agent-actor-containment
description: >-
  Establish what disabling a human's account does not stop when agents hold
  issued tokens, and separate the task a user authorised from the actions taken
  under it. Use during an incident where the actor is an agent and the account
  is a person's.
allowed-tools: Read, Grep, Glob

Disabling her account stops her, not them

The reflex containment step is to disable the account the logs name. When the actor is an agent holding an already-issued token, that step changes nothing: the token is valid until it expires, and the agent keeps acting. Containment has to name the credential and the workload, not the person.

When to use this

Any incident where an agent acted on a user's behalf, and before any containment decision that starts by disabling an account.

Procedure

1 — Enumerate live sessions and issued tokens per actor. Human sessions, agent sessions, and the tokens each holds with their expiry. This list is the containment surface and it is usually longer than expected.

2 — Simulate disabling the human's account. Record what stops and what does not. Already-issued tokens continuing to work is the finding, and it needs to be stated before the containment call is made.

3 — Interview to separate authorisation from action. The user authorised a task. Which of the actions taken under it did they know about, ask for, or see? The answer is usually "the first one", and it changes the incident's character entirely.

4 — Draw the actor chain. User, orchestrator, worker agent, downstream. The logs show one actor; the chain shows three. Name each and what each can still do.

5 — Choose levers by what they actually stop. Account disable, token revocation, workload termination, downstream block. Record the effect and the collateral of each, and pick from that table rather than from habit.

Example

Input — the fixture committed at the top of scripts/agent_actor_containment.py. Edit it and re-run: the buckets, counts and verdicts below are derived from it, not hard-coded.

Output — the opening lines of a real run:

INSTINCT 1 — disable dana@corp's account
   dana@corp (human)      can act: True   account disabled, but the issued token is still valid
   patch-agent            can act: True   active
   deploy-agent           can act: True   active
   → the agents were never using her account interactively; they hold
     their own issued tokens, and one of them is acting AS her.

INSTINCT 2 — interview the user

The run continues past this. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.

Output contract

{
  "sessions": [{"actor": "str", "kind": "human|agent", "tokens": [{"id": "str", "expires_in_s": 0}]}],
  "disable_human": {"stops": ["str"], "does_not_stop": ["str"]},
  "interview": {"authorised": "str", "aware_of": ["str"], "unaware_of": ["str"]},
  "chain": ["str"],
  "levers": [{"lever": "str", "stops": ["str"], "collateral": ["str"]}]
}

Failure modes

  • Starting with the account. It is the one lever that does not touch the actor.
  • Recording the user as having authorised the actions. They authorised a task.
  • Containing the worker and not the orchestrator. It will start another.

Three ways to do this lesson. Pick one. They run the same procedure against the same code — what changes is who drives it, and how much you see.

1In your AI agent — you are taught

The agent reads the lesson, explains the idea, fetches the code, runs the check and answers your questions as you go. This is the one to take if you are here to learn.

Install it, once. From the folder you cloned. --all does every agent it finds on your machine:

python3 scripts/install_skills.py --all --lessons E3.4

Then restart your agent and open it in that folder. On Windows, if python3 says Python was not found, use python instead.

Then pick e3-4-when-the-actor-is-an-agent:

agentinstall just for this agentstart it
Claude Codepython3 scripts/install_skills.py --tool claude --lessons E3.4type /e3-4-when-the-actor-is-an-agent
GitHub Copilot (VS Code)python3 scripts/install_skills.py --tool copilot --lessons E3.4type /e3-4-when-the-actor-is-an-agent in Chat
Cursorpython3 scripts/install_skills.py --tool cursor --lessons E3.4type / in Agent chat and search for it
Codexpython3 scripts/install_skills.py --tool agents --lessons E3.4type $e3-4-when-the-actor-is-an-agent, or run /skills

2As one Python command — you just run it

No agent, no conversation. The same lesson executes and prints the same readback. Take this one if you have no assistant, if you are reviewing rather than learning, or if you want the result without the teaching around it.

python3 scripts/lesson.py E3.4

3Read the code, and the difference — nothing runs

Neither of the above, and no model needed. The first command writes CyberTravels exactly as it stood at the end of this lesson; the second prints the diff — the lines this lesson added or changed, and nothing from any later one.

python3 scripts/checkpoint.py --at E3.4 --out work/cybertravels
python3 scripts/checkpoint.py --at E3.4 --diff

On Windows, type python wherever these say python3 — and use \ instead of / in the paths. Everything else is identical. A0.0 step 2 explains why.

Ways 1 and 2 need a model; way 3 does not. A signed-in Claude Code CLI needs no API key, and any OpenAI-compatible endpoint works too. With neither, the audit exits 2 and says so rather than inventing an answer. A0.0 sets this up.

Ways 1 and 2 both end with the same readback: What I did, What changed, The number and Read this next. A step that was skipped or refused is reported as exactly that, never as a pass.

If you did the last lesson’s challenge, expect this to stop. Most challenges ask you to edit the code, and ways 1 and 2 will not overwrite your edits: you get stopped, not a failure, with two options — --out for a fresh folder that keeps your work, or --force to discard it and start this lesson clean.

✓What you just proved

Disabling the human's account leaves both agents able to act on already-issued tokens. The interview establishes the user authorised a task, not the actions. The chain shows three actors where the logs show one. Revoking patch-agent's identity stops it in 12 seconds while dana and deploy-agent continue working.

✎Your turn

Write your agentic incident runbook's first three steps. If step one is "disable the user account", rewrite it — and check whether you can currently revoke a single agent identity at all.

Tools used

KeycloakOpenSearch

Skill source: skills/response/agent-actor-containment

← PreviousE3.3 · The context that makes agent triage work