Lion Cipher Lab
Parallelize an IR agent's tool calls with a dependency graph, measure the speedup, and catch the ordering bugs
- AI Security
- Advanced
- ~90 min
- Free · no account required
Why it matters
Incident-response agents are getting faster the obvious way: instead of calling one tool, waiting, then calling the next, they fire many tool calls at once. Research systems such as LLMCompiler report several-fold latency wins from exactly that. For lookups it is pure profit - asking three reputation services about an IP address in parallel changes nothing but the wait. But an incident plan is not only lookups. It also captures a host's memory, collects its live network connections, isolates it from the network, revokes a user's sessions and resets their password, and some of those steps…
What you'll learn
- representing an incident-response agent's plan as a dependency graph and executing it with graphlib.TopologicalSorter's prepare / get_ready / done loop, on a simulated clock so every run is exact and repeatable
- telling a DATA dependency (a call uses another call's output) apart from an ORDERING constraint (no data flows, but the order still decides whether evidence survives), and showing with numbers that a data-only graph still isolated hosts mid-capture 52 times
- measuring makespan, speedup and rule violations side by side for sequential, naive asyncio.gather and graph execution: 1.00x / 3.17x with 144 violations / 2.55x with 0
- applying RFC 3227's order of volatility and the revoke-sessions-before-password-reset rule as machine-checked ordering rules instead of hoping the planner remembers them
- finding an ordering rule the planner never declared (quarantine before memory capture ends, 16 violations) and closing it with side-effect classes for 37 ms of extra total time
- showing where concurrency stops paying: the per-incident critical path caps the speedup at 2.55x, and past 32 workers a rate-limited reputation API starts answering HTTP 429 until a per-tool gate is added
Steps in this lab
- The words first: tool call, plan, dependency graph, makespan, order of volatility - and the fact that the agent is a stub
- Open a terminal, check Python, make a scratch folder (Windows, macOS, Linux)
- Write the stub planner: 40 incidents, one plan each, with 'needs' and 'after'
- Why some edges are not data: order of volatility, and revoke before reset
- Write the executor: graphlib on a simulated clock, five edge policies, one rule checker
- Measure all 40 incidents: sequential, gather, data-only graph, declared graph
- Read it honestly: what the safe order costs
- The rule nobody declared: quarantine_file, and side-effect classes as the fix
- Where speedup stops: the critical path, the worker cap, and HTTP 429
- Confirm with real asyncio tasks (about 10 seconds of real waiting)
- Why this, not that - and when NOT to parallelize
- The way a pro does it differently
- Ship it: re-run, break a rule on purpose, and clean up