Agentic AI Research Agent
An agent that plans, calls tools, and shows its work
Stack
Frontend
- Next.js 14 App Router chat streaming the agent trace
- Angular 18 standalone admin with guarded routes
- CKEditor 5 knowledge-base editor with a custom upload adapter
- EventSource over server-sent events, no polling
- Markdown rendering for tool output and answers
Backend & Data
- Node 20, TypeScript, Express
- ReAct agent loop with a bounded step budget
- Provider interface: a hosted model or a deterministic mock
- Store driver interface: hosted Postgres and object storage, or a local JSON file
- SQL migration runner tracking applied files
- Shared-secret auth on every privileged endpoint
How it works
Problem
An agent that answers in one shot is impossible to debug and hard to trust. I wanted the reasoning visible as it happens, every run replayable afterwards, and the whole system runnable with no key and no database so it could be demonstrated anywhere.
What I built
- A reason-and-act loop where each turn returns exactly one JSON object — a tool call or a final answer — executed, observed and fed back until the agent answers or hits its step limit.
- Three tools behind one interface: keyword search over an editable knowledge base, a calculator, and a clock.
- A chat frontend streaming thoughts, tool calls and observations over server-sent events as they happen.
- An admin console with run history and filters, a step-by-step trace per run, usage statistics, and a rich-text knowledge-base editor.
- Tool on/off switches that the agent loop reads before every run.
Technical decisions & trade-offs
- The calculator is a hand-written recursive-descent parser rather than eval, because model output is untrusted input and arithmetic is not worth an injection surface.
- Tool toggles are enforced twice — disabled tools are absent from the prompt, and rejected at execution if the model asks anyway.
- The model sits behind a one-method interface with a deterministic mock beside the real provider, so the loop is testable offline with no key and no network.
- The whole trace is one JSON row. Reads are a single query and the step shape can evolve without a migration; the cost is no SQL inside steps, so statistics aggregate in application code.
- Row-level security is on with no policies at all — the server-side key bypasses it by design, so a leaked public key can read and write nothing.
Challenges solved
- Models drift off format, so the parser tolerates code fences and stray prose, and a failed parse records an error step and re-prompts inside the same step budget rather than failing the run.
- The knowledge base keeps rich HTML for authors and a derived plain-text copy for retrieval, so formatting survives without polluting what the agent searches.
- Editor images upload to object storage and return as URLs rather than inline base64, which would have bloated every row carrying a picture.
Outcome
A complete agent stack that runs offline in mock mode with no key and no database, and against hosted Postgres and a real model when configured. Every run replays step by step — and because the loop never depended on a provider, the same code runs in a browser as a demo.