Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Block 1: Your first deepagent

Welcome. This is a setup exercise. The goal is not to build something clever yet, but to confirm your environment works and to walk through the basic pieces of an agent built with deepagents:

  • A model (we use OpenRouter via langchain-openrouter)
  • A tool the agent can call (Tavily web search)
  • A backend for the agent filesystem (so it can write answer.md)
  • A system prompt that tells the agent who it is and what to do
  • Tracing with Langfuse so you can see what the agent did

By the end you should have a small research agent that answers a question by searching the web and saving a markdown report in artifacts/.

1. Prerequisites

Follow the Getting Started section in the top-level README: install dependencies with uv sync and create a .env file with your OpenRouter, Tavily, and Langfuse keys.

2. What you need to do

The Python harness in main.py is already wired up (model, tool, backend, and Langfuse tracing). Your job is to write the system prompt:

  1. Open prompts/research_agent.md.j2 and replace the placeholder with a real prompt. The file has a short checklist in a Jinja comment (role, tools, output) to guide you.
  2. Run the agent (see below), read the report at artifacts/answer.md, and open the run in Langfuse.

There is no single right prompt. Try something, run it, and iterate.

3. Run it

From the repository root:

uv run python -m exercises.block1.main

You should see the agent think, call internet_search a few times, and print a final message. A file answer.md should appear in exercises/block1/artifacts/.

4. Verify

  • Open the final report at exercises/block1/artifacts/answer.md.
  • Open the run in Langfuse and click through the trace. You should see the tool calls, their arguments, and the model responses for each step.

5. Stretch goals

Once the basic run works, pick one or more of these (in any order):

5.1 Tour the Langfuse trace

Open your run in Langfuse and find each part of the harness in the trace:

  • The system prompt the agent received
  • Each **internet_search** tool call (arguments and response)
  • The model intermediate reasoning between tool calls
  • The final **write_file** (or equivalent) that created answer.md

Write down which span corresponds to what.

5.2 Add or modify a tool

Pick one variant:

  • Add a tool: Implement fetch_url(url: str) that returns page text (for example via tavily_client.extract(url)), register it in create_deep_agent, and update your prompt so the agent uses fetch_url for deep reads after internet_search.
  • Modify a tool: Change internet_search, for example always pass topic="news", or truncate each result to N characters, and observe how the agent adapts.

5.3 Inject a flaky tool

Wrap internet_search so every second call raises an error, then watch what the agent does in Langfuse (retry, different query, give up?).

_call_count = 0

def internet_search(query: str, ...):
    global _call_count
    _call_count += 1
    if _call_count % 2 == 0:
        raise RuntimeError("Simulated transient error from internet_search")
    return tavily_client.search(query, ...)

Write a short note on what you observed.

6. If you get stuck

A reference implementation (including a filled-in prompt) is in solutions/block1/. Try not to peek until you have given the prompt an honest attempt.