How to build your first AI agent in an afternoon
A working plan for consultants and product people who want to go from zero to a running agent by five o'clock: one task, hardcoded data, a loop you control, and a stop point. No buzzwords.
- Agents
- Prompting
- Tools
Revised 3 times, last on 5 September 2026· show· hide
- 12 Jun 2025Swapped the example away from naive function calling toward LangGraph, after a client project made it clear the cyclic-graph model is worth the up-front cognitive cost.
- 3 Oct 2025Softened the 'no sophisticated RAG' advice. After six more production builds I think a tiny retrieval step in v1 is fine if you keep it honest about its limits.
- 5 Sep 2026Rewrote as an hour-by-hour afternoon plan with a real three-node graph, a five o'clock checklist, and a list of what to leave for next week.
You have a Friday afternoon, a laptop, and a task that has been quietly eating an hour of someone's week for a year. By five o'clock you can have an agent doing it. Not a demo. A small, ugly, working thing with a stop point.
The key is to refuse the two temptations that kill afternoons: the architecture diagram and the phrase "it should figure it out". Agents need guardrails, and first agents need hardcoded data.
Here is the afternoon, hour by hour.
1. Start with the why
13:00. Before writing a line of code or a prompt, answer three questions on paper:
- What is the manual task, exactly? Watch someone do it once if you can.
- Where does the data come from? Name the file, the page, the inbox.
- What does the finished output look like? Open a real example.
If your answer includes "it should figure things out autonomously", stop. You are describing a hope, not a task. Agents need guardrails: a defined input, a defined output, and a list of things they must not do.
A decision rule that saves a lot of afternoons: if the task is one model call with a good prompt, it is not an agent, and you should build the prompt instead. It becomes an agent when it needs to loop: draft, check, fix, check again, and stop when a condition holds. Most real work has one loop in it. Find that loop.
Pick the smallest version. "Turn the weekly supplier emails into a one-table status update" is an afternoon. "Manage supplier relationships" is a career.
2. Choose the smallest shape that loops
13:30. Every first agent I build has the same four nodes, whatever the task:
gather -> draft -> check -> (loop back to draft, or stop)
Gather collects the inputs. Draft asks the model for the output. Check tests the draft against rules you can write down. The loop runs until the checks pass or you hit an attempt limit. That last clause is the guardrail people forget, and it is why the agent never runs forever.
Plain Python scripts can orchestrate this. I use LangGraph because it makes the state and the loop explicit, and because in six months someone else will need to read it. This is the whole v1:
from typing import List, TypedDict
from langgraph.graph import StateGraph, END
FIXED_CONTEXT = open("this_weeks_supplier_emails.txt").read() # hardcoded on purpose
class AgentState(TypedDict):
context: str
draft: str
issues: List[str]
attempts: int
def gather(state: AgentState) -> dict:
return {"context": FIXED_CONTEXT, "attempts": 0}
def draft(state: AgentState) -> dict:
prompt = (
"Produce a status table with columns: supplier, status, next action, date.\n"
"Use only the emails below. If a fact is missing, write 'unknown'.\n\n"
f"{state['context']}"
)
if state["issues"]:
prompt += "\n\nFix these problems in the previous draft:\n- " + "\n- ".join(state["issues"])
return {"draft": call_model(prompt), "attempts": state["attempts"] + 1}
def check(state: AgentState) -> dict:
issues = []
if "| supplier |" not in state["draft"].lower():
issues.append("missing the supplier column")
if "unknown" not in state["draft"] and "confirmed" not in state["draft"].lower():
issues.append("no dates are marked confirmed or unknown")
return {"issues": issues}
def route(state: AgentState) -> str:
if not state["issues"] or state["attempts"] >= 3:
return END
return "draft"
graph = StateGraph(AgentState)
graph.add_node("gather", gather)
graph.add_node("draft", draft)
graph.add_node("check", check)
graph.set_entry_point("gather")
graph.add_edge("gather", "draft")
graph.add_edge("draft", "check")
graph.add_conditional_edges("check", route, {"draft": "draft", END: END})
app = graph.compile()
result = app.invoke({"context": "", "draft": "", "issues": [], "attempts": 0})
print(result["draft"])
Three things to notice. The context is a file you pasted, not a retrieval system. The checks are dumb string tests you could explain to anyone. The loop stops after three attempts no matter what. That is a guardrail you can point at in a meeting.
14:30. Run it. It will produce something wrong. Good: now you have a concrete failure to fix instead of an abstract design to admire.
3. Iterate on the boring version
15:00. Do not worry about sophisticated RAG pipelines in v1. Get the prompt working reliably against a fixed context block first.
"A working agent with hardcoded data is infinitely more valuable than an architectural diagram of a system that hasn't been built yet."
The loop for the next two hours is the same one the agent runs: draft, check, fix.
- Run the agent on this week's data. Read the output next to the real example from 13:00.
- Write down the first thing that is wrong, in one sentence.
- Decide whether it is a prompt problem (the model misunderstood) or a check problem (the model did something you never told it not to do). Fix that one thing.
- Run it again.
Five or six of these cycles is a normal afternoon. Each one should add either a line to the prompt or a line to check. If you find yourself adding a new node, stop and ask whether the task got bigger than you agreed at 13:00.
16:30. Add the stop point. Whatever the agent produces, a human reads it before it goes anywhere. In v1 that means print() and a person. Do not wire the output into email, a database, or a ticketing system this afternoon. The agent prepares; the human commits.
What good looks like at five o'clock
- The agent runs end to end on real data from this week, from one command.
- The output is in the exact shape of the manual version, so the person who used to do it can judge it in thirty seconds.
- The checks catch the two or three mistakes you saw it make today.
- It stops after a fixed number of attempts and says so.
- Someone other than you has read the code and understood the loop.
- Nothing it produces reaches the outside world without a person in between.
If you have five of the six, you have an agent. If the sixth is missing, you have a risk.
What to leave for next week
- Retrieval. A tiny retrieval step in v1 is fine if you keep it honest about its limits, but it is not where the value is on day one.
- Memory across runs. Most weekly tasks do not need it, and it makes failures harder to reproduce.
- Scheduling. Run it by hand for two weeks. If it is boringly correct both times, then schedule it.
- Tools that write. Sending, editing, and submitting come after you have watched the agent be right ten times.
- A second task. Finish one. The second one is easier because you now have a shape.
This iterative approach is what separates the deployments that survive from the perpetual proofs of concept. The proof of concept was designed. The deployment was iterated.
Do this Monday
- Monday: pick the task and watch someone do it. Write the three answers from 13:00.
- Tuesday: paste this week's real input into a file. Build the four-node loop with dumb checks. Get it to run once.
- Wednesday: five draft-check-fix cycles. Add one line per cycle.
- Thursday: show the output to the person who does the task. Write down what they say, word for word.
- Friday: fix the top two things they said. Then leave it alone, and run it again next week before touching anything else.
- Agent
- A program that uses a language model to plan and take actions against a goal, not just answer a question.
- Guardrails
- Explicit constraints on what the agent may do. The antidote to 'it should figure it out autonomously'.
- LangGraph
- A workflow library for LLM apps, built around stateful cyclic graphs. Useful when your agent needs to loop.
- RAG
- Retrieval-augmented generation: the pattern of fetching relevant context before generating an answer.
Written by Yvo de Rooij, independent AI consultant and builder in Amsterdam.
Start a conversation