Home / AI Hub / Your First Agent, One Example All the Way Through
AI Hub · Agents

Your First Agent, One Example All the Way Through

Everything you need, taught through one build: an email triage agent that reads incoming email, summarizes it, and sorts it by urgency.

The Goal

An email comes in. The agent reads it, writes a one line summary, and puts it into one of three buckets: must read next hour, must read next six hours, must read next 24 hours.

That's it. That's the whole task. Everything below is just how you actually build that.

Step 1: Is This a Workflow or an Agent?

Ask yourself: could I write down, in order, every step this takes, no matter what email comes in? For this task, yes. It's always the same three moves:

  1. Read the email
  2. Summarize it
  3. Sort it into a bucket

Because the steps never change, this is a workflow, not a full agent. That's good news. Workflows are simpler, cheaper, and easier to trust. Most first builds should be a workflow, and this one is a perfectly good place to start.

A true agent would be something like: the same task, but it also decides on its own whether to draft a reply, escalate to a person, or do nothing, and that decision changes the path each time. That's a later upgrade, not where you start.

Step 2: The One Pattern This Uses (Routing)

Inside this workflow, there's exactly one moment of real decision making: sorting the email into a bucket. That's called routing. You classify the input, then send it down one of a few paths.

That's the only pattern this example needs. You don't need to learn the other four patterns (chaining, parallel work, delegating to helpers, draft then critique) to build this. They exist for more complex tasks later.

Step 3: What the Agent Needs to Do Its Job

For this task, the agent needs exactly one thing: a clear instruction that tells it how to summarize and how to decide urgency. No lookups, no external actions, nothing fancy.

That instruction is called the system prompt. Here's the one this build actually uses:

System Prompt
You are an email triage assistant. For every email you are given,
respond in exactly this format, nothing else:

SUMMARY: [one sentence summary of what the email is asking or saying]
URGENCY: [must read next hour, must read next six hours, or must read next 24 hours]
REASON: [one short sentence on why you picked that urgency level]

Guidance on urgency:
- Next hour: something time sensitive, a deadline today, an angry or urgent tone,
  anything involving money, legal, or a system being down
- Next six hours: needs a real response but nothing is actively breaking
- Next 24 hours: FYI, low stakes, can wait a day with no real cost

Notice this is strict on purpose. A vague instruction gets a vague, inconsistent result. A specific format gets something you can actually use every time.

Step 4: The Actual Code

This is the whole thing, one email in, one triaged result out.

triage.py
import os
from anthropic import Anthropic

client = Anthropic()

def triage_email(subject: str, body: str) -> dict:
    system_prompt = """
    You are an email triage assistant. For every email you are given,
    respond in exactly this format, nothing else:

    SUMMARY: [one sentence summary of what the email is asking or saying]
    URGENCY: [must read next hour, must read next six hours, or must read next 24 hours]
    REASON: [one short sentence on why you picked that urgency level]

    Guidance on urgency:
    - Next hour: something time sensitive, a deadline today, an angry or urgent tone,
      anything involving money, legal, or a system being down
    - Next six hours: needs a real response but nothing is actively breaking
    - Next 24 hours: FYI, low stakes, can wait a day with no real cost
    """

    message = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=200,
        system=system_prompt,
        messages=[{"role": "user", "content": f"Subject: {subject}\n\nBody: {body}"}]
    )

    reply_text = message.content[0].text
    lines = reply_text.strip().split("\n")
    result = {}
    for line in lines:
        if line.startswith("SUMMARY:"):
            result["summary"] = line.replace("SUMMARY:", "").strip()
        elif line.startswith("URGENCY:"):
            result["urgency"] = line.replace("URGENCY:", "").strip()
        elif line.startswith("REASON:"):
            result["reason"] = line.replace("REASON:", "").strip()

    return result

You call it like this, with one real email:

Example call
result = triage_email(
    subject="Refund not processed after 2 weeks",
    body="I was told my refund would show up in 3 to 5 business days. "
         "It has been 2 weeks and I still don't see it. I need this "
         "resolved today or I am disputing the charge with my bank."
)

print(result)
# {'summary': 'Customer says a refund is 2 weeks late and wants it resolved today.',
#  'urgency': 'must read next hour',
#  'reason': 'Involves money and an explicit same day deadline.'}

That's a real, working build for one email. Everything after this point is just making it run automatically instead of you calling it by hand.

Step 5: Making It Check Real Email Instead of One Sample

Right now it only handles the one email you hand it. To make it real, you'd add one more piece before the code above: a call that fetches your actual unread emails, using something like Gmail's API, and loops the triage function over each one.

This is the only genuinely new piece of code you'd need to add. Everything else in this guide already handles the harder part, which is what Claude does with each email once it has it.

Step 6: Where Does the Result Go?

Right now the result just prints to the screen. Pick one:

Whichever you pick, this is a small edit at the end of the function, not a redesign of anything above.

Step 7: Where Does This Actually Run?

Three real options, in order of how much setup they take:

1. Claude.ai Project
Cannot run this automatically. It's a saved workspace, not an automation. Good for testing the wording of your instruction by hand before you write any code.
2. Your own code plus a scheduler (cron)
The code above, sitting on a server you control, triggered by cron, a built-in scheduler that runs a file at times you set, like every hour. This is the standard path for this kind of task.
3. A cloud scheduled function
The same code, but hosted by a cloud provider so no server of yours has to stay on at all.
What Doesn't Apply Here

Claude Code Routines, which trigger off things happening in a GitHub code repository (a pull request opened, a release published). Since this task is triggered by an email arriving, not a code event, Routines aren't the right tool for this one. That's a good tool for a different kind of job, like automating code review, not this.

The Whole Path, One Line Each
  1. Decided it's a workflow, not a full agent, because the steps never change
  2. Used one pattern, routing, to sort into three buckets
  3. Wrote one strict instruction telling Claude exactly how to summarize and label
  4. Wrote the code that sends one email in and gets a labeled result out
  5. Will extend it to pull real unread email instead of one sample
  6. Will send the result somewhere useful instead of just printing it
  7. Will run it on a schedule using cron or a cloud function, not Routines

That's the entire build. Every concept from the longer notes lives inside this one example, and nothing here required learning a pattern or a tool this task doesn't actually use.

AI Hub
AI Agents, and How to Build Your First One →
AI Hub
Using Projects and Agents for Repeat Work →
AI Hub
Stop Searching. Start Giving AI the Whole Problem. →