A real-world agent on raw API calls (Hacker News chatbot)
- Source
- From the RAG & Agents Engineering course
- By
- Sourav Banerjee
- Last updated
- 9 Nov 2026
The project: a Hacker News chatbot
What you'll build
- A ReAct agent that answers questions about Hacker News by choosing between three tools.
- Three tools over the public Hacker News API: top stories, a story's comments, a story's page text.
- A small library that turns the classes from lesson 1 of T7.1 into code an app can import.
- A chat app that keeps one agent per browser session.
Lesson 1 of T7.1 built reflection, tool use and ReAct inline, one notebook cell at a time. This project puts the ReAct loop to work on a live source. The questions are the kind a reader of Hacker News asks: What are the top five stories right now? or What is the top story, and what are people saying about it?
The project adds no new pattern. It shows what changes when a pattern leaves the notebook: the code has to be importable, the tools return real and changing data, and a chat app has to remember earlier turns.
Architecture
Figure 1: The chatbot. The agent decides which tools to call and in what order; the tools call the public API.
| Piece | What it does | Built on |
|---|---|---|
| Agent library | The tool decorator, the tool class, and the tool-use, ReAct and reflection agents, packaged as importable modules | The classes from lesson 1 of T7.1 |
| Three tools | Top, new or best stories with their ids; the first few top-level comments of one story; the text of a story's web page | The tool contract from lesson 1 of T7.1 |
| Three helpers | Fetch one item, fetch a list of story ids, fetch a page's text. Plain functions, not tools | |
| The bot | A ReAct agent with the three tools and a system prompt that sets its persona and asks for stories as a table | Lesson 1 of T7.1's ReAct loop |
| Chat app | A Streamlit page that keeps one agent and the chat history per browser session |
Table 1: The project's five pieces.
The library comes from the open-source, MIT-licensed agentic_patterns project, adapted for the course to use the OpenAI SDK.
Following a two-step question
Ask What is the current top story, and what are people saying about it in the first five comments? The second tool needs an id that only the first tool can supply:
Figure 2: The dependent call. The story id travels from the first observation into the second call.
This is the chaining that one round of tool use cannot do (lesson 1 of T7.1's one-shot blindness). The loop handles it with no code specific to this question: the model reads the id in the observation and writes the next call. A question that needs only the story list takes one tool call.
The answers change with Hacker News, so the notebook prints no fixed result. What stays the same from run to run is the order of the calls.
Design choices worth copying
| Choice | Why |
|---|---|
| Package the agent code | An app cannot import from a notebook. The same classes now serve the notebook and the chat app |
| Keep helpers out of the tool list | The model sees only decorated tools. Fetching ids or raw pages stays plain code the model cannot call directly |
| Cap what a tool returns | Comments stop at a limit and page text is cut to 4,000 characters. One long article would otherwise fill the context |
| Return failures as text | A page that cannot be fetched comes back as an informative message, so the model can apologise or try another story |
| One agent per browser session | Two people using the app never share a history |
Table 2: Five choices and what each protects against.
The fourth row has a cost lesson 5 of T7.1 names: a failure returned as text reaches the model as a normal result, so monitoring that counts errors never sees it.
Limits
- Live data. Answers differ on every run, so there is no expected answer to compare against. To test the bot, check behaviour: which tools it called, in what order, with which ids.
- Growing memory. The app puts every earlier answer in front of each new question. The prompt grows each turn (lesson 1 of T7.1's context creep), and the user's earlier questions are not kept, only the bot's answers.
- No round cap in the app. The app relies on the ReAct agent's own default limit. A production version would set it explicitly and show a fallback reply when it is reached.
The notebook runs with an OpenAI key; the Hacker News API needs none. It writes the tools, the bot and the app as files beside itself, and the chat app runs separately with Streamlit.
Run the notebooks
The code for this lesson is in these notebooks. Colab runs one in your browser: install the packages its first cell imports and set the API keys it reads. To run every notebook as written, clone the repository and use its uv environment.
| Notebook | GitHub | Colab |
|---|---|---|
| Real world agent hacker news chatbot (optional) | Open on GitHub | Open in Colab |
Key Takeaways
- A pattern becomes a product when its code is importable: the same agent class serves a notebook, a script and a chat app.
- Tools over live sources need limits on what they return and readable failure messages, or one call can flood the context or end the run.
- With live data there is no fixed expected answer, so test the agent's behaviour: the tools it chose, their order and the ids it passed.
Check yourself
1. Why can the chatbot answer what people say about the top story, when one round of tool use could not?
The comments tool needs the story's id, and that id exists only after the stories tool has run. The ReAct loop sends the first observation back to the model, which reads the id and writes the comments call. One round of tool use must write every argument before any tool runs.
2. The stories tool, the comments tool and the page-text tool all return live data. Which two guards keep a single call from flooding the agent's context?
The comments tool returns only the first few top-level comments, up to a limit, and the page-text tool cuts a page to 4,000 characters. Without them, one long thread or article could fill the context window.
3. You want a regression test for the chatbot, but the top stories change every hour. What can the test check?
The behaviour rather than the text: for the two-step question, that the agent called the stories tool first, then the comments tool with the id from the first observation, and then gave a final response. Replacing the tools with stubs that return fixed stories makes the answer text checkable too.