This repo is a minimal, educational starter for building a chatbot that can chat with a docs page URL or a codebase via a GitHub repo URL using:
- Next.js App Router (UI + API route)
- AI SDK (
ai,@ai-sdk/react,@ai-sdk/openai,@ai-sdk/anthropic) for streaming UI messages + tool calls - A ToolLoopAgent that can call tools to fetch docs pages or read code
- A small tool UI renderer that shows retrieval/summarization progress/output inside the chat
It’s intentionally small so you can fork it and create your own custom variant (different models, tools, schemas, UI, and routing).
- Chat UI (Vercel-ish dark, mobile-first) with a fixed composer + suggestion pills (
app/page.tsx,components/chat-input.tsx) - Tool UI that renders tool progress/output inline as “cards” (
components/docs-view.tsx) - Single API endpoint that streams agent UI messages (
app/api/chat/route.ts) - Agent definition with tools and model selection (
agent/docs-agent.tsx) - Documentation tool that can fetch a docs page or read a GitHub repo into structured docs (
tool/docs-tool.ts)
app/page.tsx uses useChat() from @ai-sdk/react. By default it POSTs to /api/chat with { messages }, and receives a streaming response of UI message “parts” (text, step markers, tool calls).
app/api/chat/route.ts passes the incoming messages to createAgentUIStreamResponse({ agent, uiMessages }), which streams back UI-friendly message parts.
agent/docs-agent.tsx defines a ToolLoopAgent that uses a provider model and a tools map:
- Tool name:
docs - Tool implementation:
docsTool
The agent can emit normal text and invoke tools during its reasoning loop.
tool/docs-tool.ts defines a streaming tool via tool({ inputSchema, execute }):
inputSchema: validates tool inputs withzodexecute: is an async generator (async *) that can yield intermediate states
This tool yields { state: "loading" } first, then { state: "ready", docs: { ... } }.
When the agent calls a tool, useChat() receives a message part like tool-docs. app/page.tsx routes those parts into components/docs-view.tsx, which renders:
- input streaming/available (the tool is about to run)
- output available (loading/ready)
- output error
- Node.js (modern LTS recommended)
- Bun (recommended) or npm/pnpm/yarn
- An API key for OpenAI, Anthropic, or OpenRouter
Using Bun:
bun installUsing npm:
npm installUse the provider and model selectors in the header, then paste the matching API key. Keys are stored locally in your browser storage and sent with each request.
Notes:
- Choose a provider/model pair that your key supports.
- The included docs tool can fetch a docs URL or read a GitHub repo; keep inputs scoped to avoid slow responses.
bun devThen open http://localhost:3000.
Try prompts like:
- “Chat with https://example.com/docs and summarize the key sections.”
- “Load https://docs.myproduct.com and answer: how do I create a token?”
- “Chat with https://github.com/acme/my-repo and explain the
app/folder.”
Edit lib/llm.ts:
- Update the model lists for OpenAI, Anthropic, and OpenRouter.
- Adjust default provider/model values as needed.
Keep the rest of the architecture the same.
-
Create a tool file (e.g.
tool/api-docs-tool.ts)- Define
tool({ description, inputSchema, execute }) - Use
zodto validate inputs - Yield intermediate states if you want progressive UI updates
- Define
-
Register the tool on the agent
In agent/docs-agent.tsx, add it to tools:
tools: { docs: docsTool, apiDocs: apiDocsTool }
- Render it in the UI
In app/page.tsx, add a new case "tool-api-docs": ... and create a renderer component similar to components/docs-view.tsx.
tool/docs-tool.ts can be extended with documentation-focused capabilities that:
- Accepts a URL or repo scope (docs page URL, GitHub repo URL, or a subpath)
- Reads content and extracts purpose, public APIs, and usage
- Emits structured output (JSON) for sections like Overview, API, and Examples
Key files:
app/page.tsx: chat shell (header/content/footer), message loop + routing message “parts”, builds dynamic suggestion promptscomponents/chat-input.tsx: composer (textarea), Enter-to-send, and optional suggestion pillscomponents/docs-view.tsx: tool output displayapp/globals.css: global styling (Tailwind)
app/
api/chat/route.ts # POST /api/chat → streams agent UI response
globals.css # global theme + markdown tweaks
layout.tsx # app shell + fonts
page.tsx # Chat UI using useChat()
agent/
docs-agent.tsx # ToolLoopAgent definition (model + tools)
tool/
docs-tool.ts # Streaming tool (zod schema + execute generator)
components/
chat-input.tsx # Chat input component
docs-view.tsx # Tool invocation renderer
public/
assets/
chat-conversation.png
logo.png
bun dev # run locally
bun build # production build
bun start # run production server
bun lint # lintThis is a standard Next.js App Router project. On Vercel (or similar), ensure:
- Users will supply their provider/model and API key in the UI
- Your chosen model/provider is supported in the runtime you deploy to
- Cause:
useChat()disables input unlessstatus === "ready". - Fix:
- Make sure the dev server is running (
bun dev) and the page loads without errors. - If it becomes stuck after an error, refresh the page to reset state.
- Make sure the dev server is running (
- Cause: Missing or invalid API key for the selected provider/model.
- Fix:
- Re-enter the key in the UI and confirm the provider/model pairing.
- Cause: The tool threw an error (fetch/read failure, bad input, provider response not OK).
- Fix:
- Try a smaller scope like a single docs page or a subfolder in the repo.
- Ensure the URL you requested exists and is reachable.
- For GitHub, ensure the repo URL is public or your tooling supports auth.
- Check the server console for the full error message.
- Cause: The tool is processing too many files/pages at once.
- Fix:
- Scope requests to a folder/file or a single docs page.
- Add caching or precomputed summaries for large repos or docs sites.
- Cause: The tool currently returns a JSON string and the view renders it directly.
- Fix:
- Return a structured object from the tool and render a richer UI in
components/chat-view.tsx.
- Return a structured object from the tool and render a richer UI in
MIT