Build a NIST Incident Response Agent

Use Claude AI to triage AWS security events with the NIST 800-61r3 framework.

Introduction

30 Second Summary

When a security breach happens, every minute counts. Organizations need a structured process to detect threats, contain damage, and recover quickly.

In this project, you will build a command-line AI agent that analyzes simulated AWS security events and generates structured incident response reports following the NIST SP 800-61r3 lifecycle.

What You'll Build

A Python script that sends simulated CloudTrail-style security events to Claude, which returns NIST-aligned incident response reports covering detection, severity classification, containment, recovery, and lessons learned.

By the end of this project, you'll have:

  • A JSON file of simulated AWS security events covering unauthorized API calls, exposed S3 buckets, and credential compromise.
  • A Python script that connects to Claude via the Anthropic Python SDK and sends events with a NIST-structured system prompt.
  • Formatted incident response reports printed to your terminal, complete with severity classifications and actionable recommendations.
  • Secret Mission: Add tool-calling so the agent can enrich events with additional context lookups during analysis.

Are there any prerequisites?

You just need basic familiarity with running commands in a terminal. No prior cybersecurity or AI experience is required.

Before We Start

Before We Start...

Set Up Your Environment

Before you can build your AI incident response agent, you need a clean workspace with the right tools installed.

In this step, you'll create a project folder, set up an isolated Python environment, and connect to the Anthropic API so your agent can talk to Claude.

In this step, get ready to:
  • Create a project folder and Python virtual environment.
  • Install the Anthropic Python SDK.
  • Set up your Anthropic account and API key.
Create a project folder and virtual environment

A virtual environment keeps your project's packages separate from the rest of your system.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir nist-ir-agent
cd nist-ir-agent
  • Create a virtual environment inside your project folder by running this command:

macOS

python3 -m venv venv

Windows

python -m venv venv

What is a virtual environment?

Think of a virtual environment as a sealed box for your project's packages. Without one, installing a package for this project could conflict with packages from a different project on your computer.

The venv folder holds a copy of Python and any packages you install, completely isolated from the rest of your system.

  • Confirm the virtual environment was created by running:
ls

You should see a venv folder in the output.

  • Activate the virtual environment by running this command:

macOS

source venv/bin/activate

Windows

.\venv\Scripts\activate

Your terminal prompt now shows (venv) at the beginning. This confirms the virtual environment is active.

Don't see (venv) in your prompt?

  • Make sure you ran the activate command from inside the nist-ir-agent folder, not from the Desktop.
  • On Windows, if you see an error about running scripts being disabled, run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned first, then try the activate command again.
  • Still stuck? Help me activate my Python virtual environment.
Install the Anthropic Python SDK

The Anthropic Python SDK is the official library for talking to Claude's API from Python code.

  • Install the anthropic package by running this command:
pip install anthropic

What does this install?

The anthropic package handles authentication, request formatting, and response parsing when you send events to Claude for analysis. It saves you from writing raw HTTP calls yourself.

  • Verify the installation succeeded by running:
pip show anthropic

You should see package details including a Name and Version field printed in the terminal.

Seeing 'pip not found'?

  • Make sure your virtual environment is still active. You should see (venv) at the start of your terminal prompt.
  • On macOS, try pip3 instead of pip.
  • Need more help? Help me fix my pip install for the Anthropic SDK.
Create your Anthropic account and set your API key

Your agent needs an API key to authenticate with Claude. You'll generate one from the Anthropic developer console.

  • Open console.anthropic.com in your browser.
  • Click Sign Up and create your account.
  • Once logged in, click Settings in the navigation menu.
  • Select API Keys from the left sidebar.
  • Click Create Key.
  • Give it a descriptive name like nist-ir-agent and click Create Key again.
  • Copy the key that appears. This is the only time you can see the full key, so save it somewhere safe.

What is an API key?

An API key is like a password that lets your Python script talk to Claude. It proves to Anthropic that you have permission to use their AI model.

New Anthropic accounts receive $5 in free credits. This project uses less than $0.05 total, so you can run it many times without worrying about cost.

Keep your API key secret

Never share your API key publicly or commit it to a code repository. Anyone with your key can make API calls charged to your account.

  • Back in your terminal (with the virtual environment still active), set the API key as an environment variable by running this command:

macOS

export ANTHROPIC_API_KEY='your-api-key-here'

Replace your-api-key-here with the key you just copied from the Anthropic console.

Windows

$env:ANTHROPIC_API_KEY = "your-api-key-here"

Replace your-api-key-here with the key you just copied from the Anthropic console.

Why an environment variable?

Storing your key in an environment variable keeps it out of your source code. The Anthropic SDK automatically reads from the ANTHROPIC_API_KEY variable, so your script never needs to contain the raw key.

  • Verify the key is set by running this command:

macOS

echo $ANTHROPIC_API_KEY

Windows

echo $env:ANTHROPIC_API_KEY

You should see your API key printed in the terminal. If it shows a blank line, re-run the export command above.

Key not showing up?

  • Make sure there are no extra spaces around the = sign in the export command.
  • On Windows, check that you used $env:ANTHROPIC_API_KEY (with the $env: prefix) and not set ANTHROPIC_API_KEY. The set command only works in Command Prompt, not PowerShell.
  • The environment variable only lasts for this terminal session. If you close and reopen the terminal, you need to set it again.
  • Need more help? Help me set my Anthropic API key as an environment variable.

Your workspace is ready. Next up, you'll create the simulated security events that your AI agent will analyze.

Create Simulated Security Events

Your environment is set up and ready to go. Now your AI agent needs something to actually analyze.

Security teams rely on event logs from services like AWS CloudTrail to detect suspicious activity in their cloud environments. In this step, you'll create a set of simulated security events that mirror real-world AWS incidents.

In this step, get ready to:
  • Learn the anatomy of a CloudTrail-style security event.
  • Create a JSON file containing three simulated AWS security incidents.
Understand the event structure

CloudTrail logs capture every API call made in an AWS environment. Each event is a JSON object packed with details that security analysts use to figure out what happened, who did it, and how bad it is.

Here are the key fields your simulated events will include:

  • event_type categorizes what kind of incident occurred (unauthorized access, policy change, credential misuse).
  • source_ip tells you where the request came from. Unexpected IPs are a red flag.
  • user_identity is the IAM ARN identifying who performed the action.
  • action and resource describe which AWS API was called and what it targeted.
  • error_code reveals whether the action succeeded or was denied. A null value means the action went through.
  • additional_context provides surrounding clues like behavioral patterns and timing anomalies.

What is AWS CloudTrail?

CloudTrail is an AWS service that records every API call made in your AWS account. Think of it as a security camera for your cloud infrastructure.

In this project, you won't connect to a real AWS account. Instead, you'll create simulated events that look just like real CloudTrail logs. This lets you focus on building the AI agent without needing any AWS setup.

Create the events.json file

Your agent needs three different types of security incidents to analyze. Each one tests a different aspect of the NIST incident response framework.

  • Create a new file called events.json inside your nist-ir-agent folder, then paste in the following content:
[
  {
    "event_id": "EVT-001",
    "event_time": "2026-05-01T14:23:45Z",
    "event_type": "UnauthorizedAPICall",
    "source_ip": "203.0.113.42",
    "user_identity": "arn:aws:iam::123456789012:user/external-contractor",
    "action": "s3:DeleteBucket",
    "resource": "arn:aws:s3:::production-database-backups",
    "region": "us-east-1",
    "error_code": "AccessDenied",
    "error_message": "User does not have permission to perform s3:DeleteBucket",
    "user_agent": "aws-cli/2.15.0 Python/3.11.6 Windows/10",
    "additional_context": "This user typically only accesses the dev-assets bucket. Three similar denied requests occurred in the past 10 minutes targeting different production buckets."
  },
  {
    "event_id": "EVT-002",
    "event_time": "2026-05-01T15:01:12Z",
    "event_type": "S3BucketPolicyChange",
    "source_ip": "10.0.4.55",
    "user_identity": "arn:aws:iam::123456789012:user/junior-developer",
    "action": "s3:PutBucketPolicy",
    "resource": "arn:aws:s3:::customer-pii-records",
    "region": "us-east-1",
    "error_code": null,
    "error_message": null,
    "user_agent": "console.aws.amazon.com",
    "additional_context": "The new bucket policy grants s3:GetObject to Principal '*', effectively making the bucket publicly readable. This bucket contains customer personally identifiable information. The change was made outside of normal business hours (3:01 AM local time)."
  },
  {
    "event_id": "EVT-003",
    "event_time": "2026-05-01T16:45:33Z",
    "event_type": "CredentialCompromise",
    "source_ip": "198.51.100.77",
    "user_identity": "arn:aws:iam::123456789012:user/admin-ops",
    "action": "sts:GetCallerIdentity",
    "resource": "arn:aws:iam::123456789012:user/admin-ops",
    "region": "eu-west-1",
    "error_code": null,
    "error_message": null,
    "user_agent": "python-requests/2.31.0",
    "additional_context": "This account experienced 47 failed ConsoleLogin attempts from 12 different IPs over the past hour. A successful programmatic authentication then occurred from IP 198.51.100.77 (geolocated to a country where the organization has no operations). The user normally authenticates from US-based corporate IPs only. The sts:GetCallerIdentity call is commonly used by attackers to verify stolen credentials work."
  }
]

What do these three events represent?

  • EVT-001 (UnauthorizedAPICall) is an external contractor trying to delete a production S3 bucket. The request was denied, but the pattern of probing multiple production buckets suggests deliberate reconnaissance.
  • EVT-002 (S3BucketPolicyChange) is a junior developer making a bucket containing customer PII publicly readable at 3 AM. The null error code means the action actually succeeded.
  • EVT-003 (CredentialCompromise) is a likely account takeover. After 47 failed logins, someone authenticated from a foreign IP and ran sts:GetCallerIdentity. That call is a classic attacker fingerprint for verifying stolen credentials.
  • Save events.json.
  • Confirm the file exists by running this command in your terminal:
dir

You should see events.json listed in the output.

Don't see events.json?

  • Make sure your terminal is in the nist-ir-agent folder. Run cd nist-ir-agent if you're in the parent directory.
  • Check that you saved the file with the exact name events.json (not events.json.txt or Events.json). File names are case-sensitive in Python.
  • If you see the file but it seems empty, open it and verify you pasted the full JSON content starting with [ and ending with ].

Still stuck? Ask for help.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete events.json file. Make sure your version matches this exactly.

[
  {
    "event_id": "EVT-001",
    "event_time": "2026-05-01T14:23:45Z",
    "event_type": "UnauthorizedAPICall",
    "source_ip": "203.0.113.42",
    "user_identity": "arn:aws:iam::123456789012:user/external-contractor",
    "action": "s3:DeleteBucket",
    "resource": "arn:aws:s3:::production-database-backups",
    "region": "us-east-1",
    "error_code": "AccessDenied",
    "error_message": "User does not have permission to perform s3:DeleteBucket",
    "user_agent": "aws-cli/2.15.0 Python/3.11.6 Windows/10",
    "additional_context": "This user typically only accesses the dev-assets bucket. Three similar denied requests occurred in the past 10 minutes targeting different production buckets."
  },
  {
    "event_id": "EVT-002",
    "event_time": "2026-05-01T15:01:12Z",
    "event_type": "S3BucketPolicyChange",
    "source_ip": "10.0.4.55",
    "user_identity": "arn:aws:iam::123456789012:user/junior-developer",
    "action": "s3:PutBucketPolicy",
    "resource": "arn:aws:s3:::customer-pii-records",
    "region": "us-east-1",
    "error_code": null,
    "error_message": null,
    "user_agent": "console.aws.amazon.com",
    "additional_context": "The new bucket policy grants s3:GetObject to Principal '*', effectively making the bucket publicly readable. This bucket contains customer personally identifiable information. The change was made outside of normal business hours (3:01 AM local time)."
  },
  {
    "event_id": "EVT-003",
    "event_time": "2026-05-01T16:45:33Z",
    "event_type": "CredentialCompromise",
    "source_ip": "198.51.100.77",
    "user_identity": "arn:aws:iam::123456789012:user/admin-ops",
    "action": "sts:GetCallerIdentity",
    "resource": "arn:aws:iam::123456789012:user/admin-ops",
    "region": "eu-west-1",
    "error_code": null,
    "error_message": null,
    "user_agent": "python-requests/2.31.0",
    "additional_context": "This account experienced 47 failed ConsoleLogin attempts from 12 different IPs over the past hour. A successful programmatic authentication then occurred from IP 198.51.100.77 (geolocated to a country where the organization has no operations). The user normally authenticates from US-based corporate IPs only. The sts:GetCallerIdentity call is commonly used by attackers to verify stolen credentials work."
  }
]

Your security events are ready. Next up, you'll build the Python agent that sends these events to Claude for NIST-based incident response analysis.

Build the NIST Incident Response Agent

Your simulated security events are ready and waiting in events.json. Now it's time to build the brain of the operation: a Python script that sends each event to Claude and gets back a structured incident response report.

The script connects to the Anthropic API, feeds each event along with a detailed NIST SP 800-61r3 system prompt, and prints the analysis to your terminal.

In this step, get ready to:
  • Set up the Anthropic client and write a function to load events from JSON.
  • Create a detailed system prompt encoding the NIST SP 800-61r3 incident response lifecycle.
  • Build the processing loop that sends events to Claude and prints reports.
Set up the Anthropic client and load events

Every Python script starts with imports. You also need a way to read your security events from the JSON file you created in the previous step.

  • Create a new file called agent.py inside your nist-ir-agent folder by running this command:
type nul > agent.py
  • Confirm the file exists by running:
dir agent.py

You should see agent.py listed in the output.

  • Open agent.py in your text editor and add the imports and the event-loading function by copying in the following code:
import json
import os
from anthropic import Anthropic


def load_events(filepath):
    """Load security events from a JSON file."""
    with open(filepath, "r") as f:
        events = json.load(f)
    return events

What does this code do?

  • json lets Python read and write JSON data. os lets the script read environment variables like your API key.
  • from anthropic import Anthropic brings in the Anthropic SDK client you installed in Step 1.
  • load_events() opens a JSON file and returns the events as a Python list. You'll use this to feed events.json into the agent.
  • Save agent.py.

You won't see a visible change yet. The next substep adds the system prompt that brings this file to life.

Seeing a red underline on the Anthropic import?

Make sure your virtual environment is still active. You should see (venv) at the beginning of your terminal prompt. If not, re-activate it from inside your nist-ir-agent folder.

If your text editor still shows an error after re-activating, try closing and reopening the file. Some editors need a refresh to detect newly installed packages.

Help me troubleshoot my Anthropic import error.

Create the NIST 800-61r3 system prompt

A system prompt tells Claude how to behave. Without one, Claude would give generic answers. Your system prompt turns it into a specialized NIST incident response analyst that produces structured reports.

What is a system prompt?

A system prompt is a set of instructions you give to an AI model before any user messages. It defines the model's role, output format, and behavior rules.

Think of it like a job description. The more specific you make it, the more consistent and useful the model's responses become.

  • In agent.py, find the blank line between your imports and the load_events function.
  • Add the following system prompt constant between them:
SYSTEM_PROMPT = """You are an expert cybersecurity incident response analyst. Your role is to analyze security events following the NIST SP 800-61r3 incident response lifecycle.

For each security event provided, produce a structured incident response report with the following sections:

## Detection and Analysis
- What happened: Describe the event in plain language.
- Indicators of Compromise (IOCs): List specific technical indicators (IPs, user agents, error patterns, timing anomalies).
- Attack vector assessment: Identify the likely attack method or misconfiguration.

## Severity Classification
- Severity: Rate as CRITICAL, HIGH, MEDIUM, or LOW.
- Justification: Explain why you chose this severity based on potential business impact, data sensitivity, and scope.
- Affected assets: List what systems or data are at risk.

## Containment and Response (NIST Respond Function)
- Immediate actions: List 2-3 specific technical steps to contain the threat RIGHT NOW.
- Short-term containment: Steps to limit damage while preserving evidence.
- Evidence preservation: What logs or artifacts should be collected before any changes.

## Recovery (NIST Recover Function)
- Eradication steps: How to remove the threat or fix the root cause.
- Recovery steps: How to restore normal operations safely.
- Validation: How to confirm the threat is fully resolved.

## Lessons Learned (NIST Identify - Improvement)
- Root cause: What allowed this to happen?
- Prevention recommendations: 2-3 specific controls or changes to prevent recurrence.
- Detection improvements: How could this be detected faster next time?

Keep your analysis concise but actionable. Use bullet points. Prioritize specific, implementable recommendations over generic advice."""

What does this system prompt do?

This prompt encodes the NIST SP 800-61r3 incident response lifecycle into five report sections. Each section maps to a phase of how real security teams handle incidents.

  • Detection and Analysis maps to the NIST Detect function. It asks Claude to describe what happened and identify indicators of compromise.
  • Severity Classification forces a concrete rating (CRITICAL, HIGH, MEDIUM, or LOW) with justification, so the report is actionable.
  • Containment, Recovery, and Lessons Learned map to the NIST Respond, Recover, and Identify (Improvement) functions respectively.
  • Save agent.py.

No visible change yet. The prompt is stored in a variable, ready to be sent to Claude in the next substep.

Build the event processing loop

You have events and a system prompt. Now you need two more pieces: a function that sends a single event to Claude for analysis, and a main function that ties everything together.

  • In agent.py, add the following function below your load_events function:
def analyze_event(client, event):
    """Send a security event to Claude for NIST-based analysis."""
    # Convert the event dictionary to a formatted JSON string
    event_text = json.dumps(event, indent=2)

    # Send the event to Claude with the NIST system prompt
    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1500,
        system=SYSTEM_PROMPT,
        messages=[
            {
                "role": "user",
                "content": f"Analyze the following security event and produce a full incident response report:\n\n{event_text}",
            }
        ],
    )

    # Return just the text content from Claude's response
    return message.content[0].text

What does this function do?

  • json.dumps(event, indent=2) converts the Python dictionary into a readable JSON string so Claude can parse it.
  • client.messages.create() sends a request to the Anthropic API. The system parameter passes your NIST prompt, and messages contains the actual event data for analysis.
  • model="claude-haiku-4-5" selects Claude Haiku 4.5, the fastest and most cost-effective Claude model. Perfect for structured analysis tasks.
  • message.content[0].text extracts the text from Claude's response object.
  • Save agent.py.

You won't see a change yet. The next chunk adds the main function that calls analyze_event() for each event.

Seeing a syntax error in the f-string?

Check that the backslash-n characters (\n\n) inside the f-string are typed correctly. Also make sure the closing parenthesis and bracket on the messages list are both present.

Help me fix a syntax error in my analyze_event function.

  • Below the analyze_event function, add the main function and the script entry point:
def main():
    """Main function to run the NIST IR agent."""
    # Initialize the Anthropic client with your API key
    client = Anthropic(
        api_key=os.environ.get("ANTHROPIC_API_KEY"),
    )

    # Load all security events from the JSON file
    events = load_events("events.json")

    # Print the agent banner
    print("=" * 70)
    print("NIST 800-61r3 AI INCIDENT RESPONSE AGENT")
    print("=" * 70)
    print(f"\nLoaded {len(events)} security events for analysis.\n")

    # Process each event and print its incident response report
    for i, event in enumerate(events, 1):
        print(f"\n{'=' * 70}")
        print(f"INCIDENT REPORT {i}/{len(events)} - Event ID: {event['event_id']}")
        print(f"Event Type: {event['event_type']}")
        print(f"Time: {event['event_time']}")
        print(f"{'=' * 70}\n")

        report = analyze_event(client, event)
        print(report)
        print(f"\n{'_' * 70}")

    print("\n\nAll events processed. Review reports above for action items.")


if __name__ == "__main__":
    main()

What does this code do?

  • Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY")) creates the API client using the environment variable you set in Step 1.
  • The for loop iterates through each event, prints a header with the event ID and type, sends it to Claude via analyze_event(), and prints the returned report.
  • if __name__ == "__main__" ensures main() only runs when you execute the script directly, not when it's imported as a module.
  • Save agent.py.

Your agent script is now complete. You'll run it in the next step to see the reports in action.

Seeing indentation errors?

Python is sensitive to whitespace. Make sure every line inside main() is indented with exactly 4 spaces. Also check that the for loop body is indented 8 spaces (4 for the function, 4 for the loop).

Help me fix indentation errors in my Python script.

✔️ Awesome, I've got everything!

Great. Double check you've saved agent.py before moving on.

ⓧ I'd like to double check the full code

Here is the full agent.py file. Make sure your code matches this exactly.

import json
import os
from anthropic import Anthropic


SYSTEM_PROMPT = """You are an expert cybersecurity incident response analyst. Your role is to analyze security events following the NIST SP 800-61r3 incident response lifecycle.

For each security event provided, produce a structured incident response report with the following sections:

## Detection and Analysis
- What happened: Describe the event in plain language.
- Indicators of Compromise (IOCs): List specific technical indicators (IPs, user agents, error patterns, timing anomalies).
- Attack vector assessment: Identify the likely attack method or misconfiguration.

## Severity Classification
- Severity: Rate as CRITICAL, HIGH, MEDIUM, or LOW.
- Justification: Explain why you chose this severity based on potential business impact, data sensitivity, and scope.
- Affected assets: List what systems or data are at risk.

## Containment and Response (NIST Respond Function)
- Immediate actions: List 2-3 specific technical steps to contain the threat RIGHT NOW.
- Short-term containment: Steps to limit damage while preserving evidence.
- Evidence preservation: What logs or artifacts should be collected before any changes.

## Recovery (NIST Recover Function)
- Eradication steps: How to remove the threat or fix the root cause.
- Recovery steps: How to restore normal operations safely.
- Validation: How to confirm the threat is fully resolved.

## Lessons Learned (NIST Identify - Improvement)
- Root cause: What allowed this to happen?
- Prevention recommendations: 2-3 specific controls or changes to prevent recurrence.
- Detection improvements: How could this be detected faster next time?

Keep your analysis concise but actionable. Use bullet points. Prioritize specific, implementable recommendations over generic advice."""


def load_events(filepath):
    """Load security events from a JSON file."""
    with open(filepath, "r") as f:
        events = json.load(f)
    return events


def analyze_event(client, event):
    """Send a security event to Claude for NIST-based analysis."""
    event_text = json.dumps(event, indent=2)

    message = client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=1500,
        system=SYSTEM_PROMPT,
        messages=[
            {
                "role": "user",
                "content": f"Analyze the following security event and produce a full incident response report:\n\n{event_text}",
            }
        ],
    )

    return message.content[0].text


def main():
    """Main function to run the NIST IR agent."""
    client = Anthropic(
        api_key=os.environ.get("ANTHROPIC_API_KEY"),
    )

    events = load_events("events.json")

    print("=" * 70)
    print("NIST 800-61r3 AI INCIDENT RESPONSE AGENT")
    print("=" * 70)
    print(f"\nLoaded {len(events)} security events for analysis.\n")

    for i, event in enumerate(events, 1):
        print(f"\n{'=' * 70}")
        print(f"INCIDENT REPORT {i}/{len(events)} - Event ID: {event['event_id']}")
        print(f"Event Type: {event['event_type']}")
        print(f"Time: {event['event_time']}")
        print(f"{'=' * 70}\n")

        report = analyze_event(client, event)
        print(report)
        print(f"\n{'_' * 70}")

    print("\n\nAll events processed. Review reports above for action items.")


if __name__ == "__main__":
    main()

Your agent is fully built. Next up, you'll run it against your three security events and see NIST-aligned incident response reports appear in your terminal.

Run the Agent and Analyze Reports

In the last step, you built the complete incident response agent. You wrote a system prompt encoding the NIST SP 800-61r3 lifecycle, a function to load events, and a processing loop that sends each event to Claude for analysis.

Now it's time to run the agent against your three simulated security events and see what it produces. You'll execute the script, read the generated incident reports, and evaluate whether the AI's analysis makes sense.

In this step, get ready to:
  • Run the agent script against three simulated security events.
  • Review and interpret the NIST-structured incident response reports.
Execute the agent script

Your agent is fully assembled. Running it sends each event from events.json to the Claude Haiku 4.5 API and prints the structured report to your terminal.

  • Make sure your virtual environment is still active. You should see (venv) at the start of your terminal prompt.
  • Make sure you are inside your nist-ir-agent folder.
  • Run the agent by executing this command:
python agent.py

The script makes three separate API calls to Claude, one for each security event. This can take 15-30 seconds total, so give it a moment.

You should see a banner that says NIST 800-61r3 AI INCIDENT RESPONSE AGENT, followed by three structured incident response reports printed to your terminal.

What should I see?

Each report starts with a header showing the event ID, event type, and timestamp. Below that, you'll see the five NIST sections: Detection and Analysis, Severity Classification, Containment and Response, Recovery, and Lessons Learned.

The exact wording varies between runs because Claude generates fresh analysis each time. The five-section structure stays consistent.

Seeing an error?

  • AuthenticationError: Your API key is missing or invalid. Double check that you set the ANTHROPIC_API_KEY environment variable in the same terminal session where you're running the script.
  • ModuleNotFoundError: No module named 'anthropic': Your virtual environment isn't active. Reactivate it with .\venv\Scripts\activate and try again.
  • FileNotFoundError: The script can't find events.json. Make sure both agent.py and events.json are in the same nist-ir-agent folder.

Still stuck? Ask for help.

Review and interpret the reports

The agent did its job. Now you do yours. A real incident responder doesn't just read a report. They evaluate whether the analysis is sound and the recommendations are actionable.

Scroll back through the three reports in your terminal. Compare the AI's analysis to what you know about each event from events.json.

  • For EVT-001, check if Claude flagged the contractor's repeated attempts to delete production S3 buckets they don't normally access.
  • For EVT-002, look at the severity rating. A PII bucket made publicly readable at 3 AM should receive the highest severity classification.
  • For EVT-003, see if Claude identified the brute-force pattern (47 failed logins) and the suspicious sts:GetCallerIdentity reconnaissance call from a foreign IP.
  • In each report's Containment and Response section, check whether the recommendations are specific (like rotating credentials or reverting a bucket policy) instead of vague.

What severity ratings should I expect?

EVT-001 (UnauthorizedAPICall) is typically rated HIGH. The access was denied, so no damage occurred. The pattern of repeated probing is the real concern.

EVT-002 (S3BucketPolicyChange) is typically rated CRITICAL. Customer PII was exposed to the public internet. The after-hours timing adds suspicion.

EVT-003 (CredentialCompromise) is also typically rated CRITICAL. An admin account was accessed from an unexpected country after a brute-force campaign. The attacker confirmed the credentials work.

Your results may differ slightly. The important thing is that the AI's justifications make sense given the event data.

Your agent is fully functional. It takes raw security events, runs them through a NIST-structured analysis, and produces actionable reports. Next up, you'll give the agent even more power by adding tool-calling for real-time event enrichment.

Secret mission

Add Tool-Calling for Event Enrichment

Your agent analyzes events in isolation right now. Real incident responders cross-reference threat intelligence databases and asset inventories before making a call. Can you give your agent the same power? In this Secret Mission, you will wire up tool-calling so Claude can look up IP reputations and resource criticality mid-analysis.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on your local machine, so there are no ongoing cloud costs. Your Anthropic API usage is billed per request, but the free $5 credit covers far more than this project needs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Python virtual environment (venv) with the anthropic package installed.
  • Project files: agent.py and events.json.
  • Anthropic account and API key.
  • ANTHROPIC_API_KEY environment variable set in your terminal session.

Keep everything running

No action needed. Choose this if you are still actively building or want to experiment with different security events and system prompts.

  • Your virtual environment and project files stay as they are.
  • Your Anthropic API key remains set for the current terminal session. It will clear automatically when you close the terminal.
  • No ongoing costs are incurred. You are only charged when you run the script and make API calls.

Pause - I'll come back to this later

Shut down running processes to free up memory. Your project files stay on disk so you can pick up where you left off.

  • Deactivate your virtual environment by running deactivate in the terminal.
  • Close your terminal window. This clears the ANTHROPIC_API_KEY environment variable from memory.
  • When you return, reactivate the virtual environment and set the API key again before running the script.

Delete - I don't want to use this again

Remove all project resources and start fresh. This deletes your project files and virtual environment permanently.

  • Deactivate the virtual environment by running deactivate in the terminal.
  • Delete the entire project folder from your Desktop.
  • Optionally, revoke your Anthropic API key at console.anthropic.com if you do not plan to use the Anthropic API again.

Nice Work!

Nice Work!

You just built an AI-powered security analyst that automates NIST SP 800-61r3 incident triage. That is a real skill that security teams use in production environments every day.

You've learned how to:

  • Build simulated AWS CloudTrail security events and connect them to Claude via the Anthropic Python SDK.
  • Design a structured system prompt that encodes the full NIST SP 800-61r3 incident response lifecycle into actionable analysis instructions.
  • Generate incident response reports with severity classification, containment steps, and recovery recommendations.
  • Secret Mission: Add tool-calling to give the agent event enrichment capabilities, making it a more autonomous analyst.

Ready to quiz yourself?