Month 2 — Orchestration & MCP
Month 1 gave you one agent with one tool. Month 2 is where the interesting failures appear, because the moment agents hand work to each other you inherit a distributed systems problem with a language model in the middle of it. Over these four weeks you will build a three-agent SOC pipeline, expose its tools through a Model Context Protocol server, and then spend a week attacking your own creation on purpose. If you have not finished Month 1, finish it first — this month assumes you already know what a tool schema is.
What you are actually building
Two things. First, the Multi-Agent SOC: alert investigator → ticket creator → report writer, with tools served over MCP. Second, the red team mini-lab, where you attack that pipeline with prompt injection and memory manipulation and log every attempt, successful or not.
The second half matters more than the first. Plenty of people can wire three agents together. Far fewer can show a written record of having broken their own system and then fixed it.
Week-by-week plan
| Week | Build | Study | Output |
|---|---|---|---|
| 5 | Agent 1 — alert investigator; enrich an alert from a local dataset | REST APIs, auth patterns, retries and idempotency | Investigator returns structured findings, not prose |
| 6 | Agents 2 and 3; define the handoff contract between all three | Cloud IAM, least privilege, secret management | Full pipeline runs end to end with a typed handoff schema |
| 7 | Move tools behind an MCP server; build the permission matrix | MCP transport, tool discovery, server-side authorization | MCP server with per-tool authorization and an approval gate |
| 8 | Red team mini-lab against your own pipeline | Prompt injection taxonomy, memory poisoning, tool abuse | Attack log with objective, payload, trace, and outcome per run |
Week 5 checklist
- Define the alert input schema and validate it before the agent sees it
- Give the investigator read-only enrichment tools only
- Make the output a typed object, not free text
Week 6 checklist
- Write the handoff contract as a schema file, not as prose in a prompt
- Assign each agent its own credential; none share one
- Place the human approval gate and document why it is there and not elsewhere
Week 7 checklist
- Stand up an MCP server and register each tool explicitly
- Enforce authorization server-side — never rely on the prompt to withhold a tool
- Fill in the tool permission matrix and commit it
Week 8 checklist
- Run at least eight distinct attacks with written objectives
- Capture the full trace for each, including the failures to exploit
- Write the mitigations you shipped and the ones you consciously deferred
Multi-Agent SOC — specification
| Agent | Role | Tools | Credential held | May write? |
|---|---|---|---|---|
| Investigator | Enriches an alert, gathers context, forms a hypothesis | read_alert, lookup_asset, search_logs | Read-only data source key | No |
| Ticket creator | Turns a validated finding into a tracked ticket | create_ticket, attach_evidence | Ticket system token, create-and-comment scope only | Create only |
| Report writer | Produces the human-readable incident summary | read_ticket, render_report | Read-only ticket token | No |
The handoff contract
The single most valuable design decision this month is refusing to let agents pass each other free-form text. Define a schema, validate it at each boundary, and reject anything that does not conform.
{
"alert_id": "string",
"verdict": "benign | suspicious | malicious | undetermined",
"confidence": "low | medium | high",
"evidence": [{ "source": "string", "excerpt": "string" }],
"recommended_action": "string",
"unresolved_questions": ["string"]
}Two properties make this contract worth the effort. It stops injected text from one stage silently becoming instructions in the next, because only declared fields cross the boundary. And it gives you a natural place to log — every handoff is a validated, serializable event you can put in an audit trail.
Why the ticket creator has no delete authority
Ticket creation is additive and recoverable: a wrong ticket is noise someone closes. Ticket deletion is destructive and often silent — it removes the evidence that the agent misbehaved in the first place. Granting delete to the agent whose input is derived from attacker-influenced alert text means a successful injection can erase its own trail.
The general rule, which you will reuse in portfolio artifacts: an agent gets the narrowest capability that still lets it finish its job, and destructive capabilities go to humans.
Where the approval gate goes
Put the gate between the ticket creator and any action that leaves your system or notifies a person: ticket creation against a real tracker, and report distribution. Do not put a gate on enrichment lookups — they are read-only, high-frequency, and gating them trains the reviewer to click through everything.
MCP as a permission-design exercise
Exposing tools over a protocol feels like plumbing. It is not. The moment a tool is discoverable over MCP, the question stops being “can my agent call this” and becomes “which callers, with which arguments, under which conditions.” That is an authorization design, and it belongs on the server.
Three rules that survive contact with reality:
- Authorize on the server, not in the prompt. A system prompt saying “only use
create_ticketfor confirmed malicious alerts” is a suggestion. Server-side checks are a control. - Validate arguments, do not just type them.
path: stringis a type. “Path must resolve inside/data/logs” is validation. Only the second one stops traversal. - Record reversibility explicitly. For every tool, write down whether its effect can be undone and by whom. If you cannot answer, the tool is not ready to expose.
Tool permission matrix
| Tool | Who may call it | Arguments validated | Reversible? | Approval required? |
|---|---|---|---|---|
search_logs | Investigator | Path inside log root; line cap | N/A (read-only) | No |
lookup_asset | Investigator | Asset ID matches known format | N/A (read-only) | No |
create_ticket | Ticket creator | Title/body length; verdict enum; evidence non-empty | Yes — ticket can be closed | Yes |
attach_evidence | Ticket creator | Ticket ID owned by this run; size cap | Yes — attachment removable | No |
render_report | Report writer | Ticket ID from this run only | Yes — report regenerable | No |
send_report | Human | Recipient on allowlist | No — cannot unsend | Yes |
Commit this table into the repo. It is one of the fastest ways to signal design maturity, and it is exactly the kind of thing described in what employers screen for.
Red team mini-lab protocol
Week 8 is a structured exercise, not free-form poking. Every attempt follows the same five steps, and every attempt gets written down.
| Step | What you do | What you record |
|---|---|---|
| 1. Objective | State the security property you are trying to violate | “Make the ticket creator write a ticket containing exfiltrated log content” |
| 2. Payload | Write the exact attack text or file | The literal payload, verbatim, in the log |
| 3. Execute | Run it against your own pipeline | Timestamp, agent version, commit hash |
| 4. Trace | Capture the full agent trace | Every tool call, arguments, and returned content |
| 5. Outcome | Worked / partially worked / blocked, and by what | The specific control that stopped it, or the gap that let it through |
Attack classes to cover at minimum:
- Direct injection in the alert body
- Indirect injection in a retrieved log line
- Instructions hidden in a field the model reads but a human skims past
- Memory manipulation — poison an earlier turn so a later decision inherits it
- Tool argument abuse — coax a path or ID outside the allowed set
- Confused deputy — get a low-privilege agent to ask a high-privilege one for the action
- Approval-gate bypass — make the request look routine enough to wave through
- Output handling — get the report writer to emit content that is dangerous when rendered
Negative results are evidence
A log entry reading “attempted indirect injection via log line, blocked by evidence-field quoting, trace attached” is worth as much as a successful exploit. It proves the control exists and that you verified it rather than assumed it. Interviewers can tell the difference between someone who designed a control and someone who tested one.
Structure your attack log so each entry stands alone: objective, payload, commit hash, trace file, outcome, mitigation status. Fifteen honest entries with three successes reads far better than three cherry-picked wins.
Exit criteria
- Three agents run end to end with a validated handoff schema
- Each agent holds exactly the credentials its role requires
- Tools are served over MCP with server-side authorization
- The tool permission matrix is committed and accurate
- The approval gate is placed on irreversible actions and justified in writing
- The attack log has at least eight entries with traces
Guided builds: Lab 2 — Multi-Agent SOC with MCP and Lab 3 — Prompt Injection Red Team. Tooling: red team tools. Next: Month 3 — Go Public.