A hosted chat app for asking questions over messy company records.
The app is built for the Codos take-home task. It lets a business user sign in, ask natural-language questions, continue multi-turn conversations, open referenced files, and get plain-language answers backed by original source documents.
- Answers questions from the bundled
data/records. - Preserves chat history across reloads and redeploys when Vercel Blob is configured.
- Resolves ambiguous entities such as similar people, regions, products, customers, and initiatives.
- Uses normalized records for interpretation, but cites only original documents in user-facing answers.
- Shows references with
[1],[2]style citations and a file preview UI. - Avoids exposing implementation details in the business-user chat experience.
Next.js chat UI
-> username/password session
-> chat history store
-> /api/query
-> isolated Vercel Sandbox
-> agent runtime over a POSIX-style workspace
-> sourced answer with original-document references
The core design decision is to keep the workspace filesystem-shaped:
AGENTS.md
data/
original company records
normalized/
entities.jsonl
facts.jsonl
causal_chains.jsonl
data/normalized/ is the preferred interpretation layer for aliases, entity resolution, stale facts, conflicts, and causal chains. It is not shown as answer evidence. Final answers cite the original company documents under data/.
This keeps the implementation simple now and leaves a clean path to a remote POSIX-compatible store later, where users or ingestion jobs can sync files without changing the query interface.
- Answer from local company records, not model memory.
- Use resolved canonical entity names in answers.
- Ask for clarification when ambiguity materially changes the answer.
- Prefer newer or more authoritative evidence when records conflict.
- Explain uncertainty and conflicts when they matter.
- Cite original documents only.
- Keep answers readable for non-technical business users.
Install dependencies:
npm installCreate local env:
cp .env.example .env.localSet either:
OPENAI_API_KEY=...or shared ChatGPT-plan auth:
codex login
base64 -i ~/.codex/auth.json | tr -d '\n'Paste the encoded value into:
CODEX_AUTH_JSON_B64=...The UI uses username/password auth. Set explicit credentials with:
APP_USERNAME=...
APP_PASSWORD=...
AUTH_SECRET=...Run the app:
npm run devRun a local command-line query:
npm run query:local -- "What is the current status of Project Confluence?"Regenerate the normalized interpretation layer with an LLM resolution pass:
npm run normalizeDeploy to Vercel with:
npx vercel deploy --yesRequired environment:
APP_USERNAME=...
APP_PASSWORD=...
AUTH_SECRET=...
CODEX_AUTH_JSON_B64=...OPENAI_API_KEY can be used instead of CODEX_AUTH_JSON_B64 for model access.
Optional but recommended:
BLOB_READ_WRITE_TOKEN=...Without Vercel Blob, chat history is stored locally under .internal/chats/ and may not survive serverless restarts or redeploys. With Vercel Blob attached, past conversations remain available in the UI.
Build:
npm run buildRun hosted smoke tests against a Vercel Preview:
VERCEL_DEPLOYMENT=https://your-preview.vercel.app npm run test:vercelRun entity-resolution evals:
VERCEL_DEPLOYMENT=https://your-preview.vercel.app npm run test:entitiesThe smoke test covers login, greeting behavior, sourced answers, multi-turn follow-up, persisted chat history, and source preview. The entity evals cover ambiguous people, stale claims, product distinctions, regional metrics, and original-document citations.
app/api/query/route.tsis the main question-answering endpoint.components/chat-app.tsxcontains the mobile-friendly chat UI.components/ai-elements/message.tsxwraps the off-the-shelf Streamdown/AI Elements-style renderer used for assistant answers and markdown source previews.lib/chat/store.tsstores and retrieves conversations.lib/codex-sandbox.tsruns the isolated hosted agent process.lib/prompt.tsbuilds the runtime answer contract.AGENTS.mddefines repository-level reasoning and citation rules.scripts/normalize-data.tsasks Codex CLI to inspect the originaldata/files, generate normalized records, and then validates the returned JSONL before writingdata/normalized/.SOLUTION.mdhas the deeper architecture write-up and tradeoffs.
- Full per-workspace permission management is not implemented in this take-home.
- The hosted runtime installs the agent CLI at execution time; a production version should use a prebuilt sandbox image.
- The normalization pipeline is intentionally small for the homework. In production it should be extended with OCR/PDF/table extraction, review queues, confidence thresholds, and incremental sync.
- Clarification persistence is specified in the agent rules, but a dedicated UI flow for reviewing and approving clarifications is future work.