cd /news/ai-agents/build-your-first-ai-agent-from-scrat… · home › topics › ai-agents › article
[ARTICLE · art-157911] src=github.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Build your first AI agent from scratch in Python: a web research agent

Humanbound published a single-file Python web research agent that runs on any OpenAI-compatible endpoint with one dependency, httpx, and four tools: search Wikipedia, fetch a page, save a note and read notes. In a recorded run on 23 October 2026, Ollama's llama3.1:8b answered from search snippets without fetching a page and got the question wrong, which the post attributes to small local models being weak at tool calling. The post states the agent is not hardened: fetched text can steer the model, persisted notes can carry a hostile page's influence into later runs, and fetch_url's private-address check is vulnerable to DNS rebinding because the name is resolved once for the check and again by the HTTP client.

read2 min views2 publishedOct 26, 2026
Build your first AI agent from scratch in Python: a web research agent
Image: Michielbdejong (auto-discovered)

A web research agent in one Python file, with no agent framework. It has four tools (search Wikipedia, fetch a page, save a note, read notes), a loop, stop rules, and a SQLite notes file that survives between runs. It accompanies the post "Build an AI agent from scratch in Python" on the Humanbound blog.

Any OpenAI-compatible endpoint works. uv installs the one dependency (httpx) from the file's header.

export AGENT_API_KEY=...                         # your key
export AGENT_BASE_URL=https://api.openai.com/v1  # default
export AGENT_MODEL=gpt-4o-mini                   # default
uv run agent.py "Who coined the term 'prompt injection', and how is it different from jailbreaking?"

The trace goes to stderr, the answer to stdout. --dump messages.json writes the full message history.

OpenRouter: set AGENT_BASE_URL=https://openrouter.ai/api/v1 and a model id such as openai/gpt-5.6-luna.

Local with Ollama, no key: AGENT_BASE_URL=http://localhost:11434/v1 AGENT_MODEL=llama3.1:8b uv run agent.py "...". Small local models are weak at tool calling. In the recorded run (examples/trace-ollama-llama3.1-8b.txt) the model answered from search snippets without fetching a page and got the answer wrong.

Set PRICE_IN_PER_MTOK and PRICE_OUT_PER_MTOK to see a cost estimate in the trace. It is computed from the API's usage numbers, not read from a bill.

The tests need no network and no key. The model is a scripted local server.

uv run --with httpx --with pytest pytest tests

The traces, answers and message histories quoted in the post, recorded on 23 October 2026, plus first-attempt/, the runs from before read_notes was fixed to match on any word. page-sizes.txt comes from measure_pages.py; token counts there are characters divided by four.

The recorded runs predate a review pass that hardened the HTML extractor, the notes queries and the error handling in run_tool, and reworded the read_notes tool description. The logic the traces show is unchanged. postfix/ holds two runs of the hardened code on the same question. The second one reads the notes the first one saved.

This agent is not hardened, and it is meant to be read before it is trusted.

  • Fetched text is written by strangers. The model can be steered by it.
  • Notes persist, so a note written because of a hostile page can mislead a later run.
  • fetch_url will request any public address, including one that carries data out in its query string. It refuses private and loopback addresses, and it does not follow redirects, so each hop is checked. The check resolves the name once and the HTTP client resolves it again when it connects, so a hostile DNS server can pass the check and then point at a private address (DNS rebinding). A production agent should connect to the address it checked.
  • It does not read robots.txt .
  • Cost is bounded only by MAX_STEPS andTOKEN_BUDGET .

Humanbound is an open-source tool that tests an agent like this over HTTP. It finds what it thinks to try, so a clean result is not proof of safety.

Apache-2.0.

── more in #ai-agents 4 stories · sorted by recency
── more on @humanbound 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/build-your-first-ai-…] indexed:0 read:2min 2026-10-26 · —