I Built a Web Search Agent Harness. Then I Checked If It Actually Deserved the Name.
The story behind building a Perplexity-style search assistant with Bun and React 19, and honestly evaluating what makes an agent harness.

Stock photo for illustration only, not from the actual event
- Developer builds a Perplexity-style web search assistant from scratch
- Questions whether the project genuinely deserves the title of an agent harness
- Explores the system architecture using Bun, React 19, Tavily, and OpenRouter
- Shares concrete plans for the upcoming v1 release on GitHub
A software developer set out to build a Perplexity-style search assistant where users can type a question, watch the system decide whether to search the web mid-answer, and receive a real response complete with clickable numbered citations. It wasn't meant to be just a chatbot wearing a search icon, but a system that genuinely reasons about whether it needs external information before responding.
The developer built it using a Bun backend, React 19 frontend, Tavily for web search, OpenRouter for the model, and Postgres underneath. After a few weeks, the system was fully functional, featuring streaming answers, clickable sources, and follow-up question support.
However, right before publishing this post and entitling it with the words agent harness, the developer paused to consider whether that claim was actually true or just a buzzword slapped on top of a fetch call with a nice system prompt.

Stock photo for illustration only, not from the actual event
The ambitious version of the post that almost got written would have claimed a multi-tool agentic harness with full observability and provider failover. In reality, none of that was true as there was only one tool, a single model provider path, and zero retries if a tool call failed mid-turn.
Before publishing, the developer reviewed the agent-loop.ts and agent-runner.ts files as if auditing someone else's PR, asking the fundamental question: what actually makes something a harness instead of a script that calls an API?
In software engineering, an agent harness refers to the scaffolding code surrounding a model that manages when tool calls happen, handles the back-and-forth communication, keeps context sane, and turns raw data into a renderable frontend format. Recognizing this boundary prevents developers from falling for marketing hype and helps build software that reliably solves real-world use cases.
Evaluating line by line against that definition confirmed it was indeed a real harness, albeit a small one restricted to a single web_search tool. A multi-tool version involving file access, code execution, and provider fallback represents a different tier of engineering.
The core logic that transforms an LLM with instructions into an agent-like behavior includes:
- Allowing the model to decide when it genuinely needs fresh information
- Differentiating between fresh queries and follow-ups to optimize latency
- Controlling the loop execution inside a verifiable scaffolding architecture
The technical stack powering this setup consists of:
- Runtime: Bun, Express 5
- Agent: @earendil-works/pi-ai with OpenRouter
- Search: Tavily API
- Database: PostgreSQL with Prisma 7
- Auth: Supabase (JWT)
- Frontend: React 19, Vite 8, assistant-ui, Tailwind CSS 4
Built intentionally as version v0, the project has concrete upgrades planned for v1. The source code is publicly available on GitHub at Saurabhsing21/Lumina, and the loop internals are documented in docs/AGENT_LOOP.md.
Source: Dev.to
Found something wrong in this article? Report an issue with this article
Comments
Leave a Comment