Support assistant that answers questions using the curated Chutes knowledge base. It provisions the repo data/ into a Sandy sandbox and runs a CLI agent there, streaming the result back to the UI.
Note on the Sandy ("Sandbox as a Service") dependency: This project uses Sandy on the dedicated production servers (new_sandy / old_sandy). Do NOT implicitly deploy Sandy changes to the bench-runner-sandy (
88.99.58.39), this server is dedicated tochutes-bench-runnerand we want to keep it stable. Do NOT change Sandy server configs (systemd overrides, autoscaler limits, resource watermarks) on Hetzner servers to accommodate this project — doing so has previously brokenchutes-bench-runnerthroughput (incident 2026-03-13). For potentially breaking changes use a separate Sandy instance or test changes in isolation first.
- UI posts a question to
POST /api/ask. - Server leases a Sandy sandbox (optionally reusing a warm sandbox).
- Server uploads
./data/**into the sandbox at/workspace/data. - Server calls
POST /api/sandboxes/:id/agent/runon Sandy withrawPrompt: true(knowledge mode). - The response is streamed (SSE) to the browser and also returned as a final answer plus source paths.
- Stable default:
claude-opus-4-6 - Claude Code is pinned to the app's internal Anthropic-compatible gateway instead of Chutes models / model-router
- The gateway keeps the Anthropic API key server-side, requires a bearer auth token plus an allowlisted
X-Chutes-Bot-Key, and enforces per-key quotas
Models are configured in:
src/app/page.tsxsrc/app/api/ask/route.ts
npm install
cp .env.example .env.local
npm run devOpen http://localhost:3000.
Required:
SANDY_BASE_URLSANDY_API_KEYCHUTES_API_KEY— Main Chutes API key for deterministic Chutes API lookups and live-data fallbacks. This may have admin rights — it is NOT exposed to sandboxes.SANDBOX_CHUTES_API_KEY— Restricted Chutes API key passed directly in the Sandyagent/runrequest so the sandboxed agent can callapi.chutes.ai. Must be a normal user key with no admin/miner privileges. Inside the sandbox the agent sees this restricted key as$CHUTES_API_KEY.ANTHROPIC_API_KEY— Real upstream Anthropic API key stored only on the server-side proxy.ANTHROPIC_PROXY_AUTH_TOKEN— Shared bearer token required by the internal Anthropic-compatible proxy.ANTHROPIC_PROXY_BOT_KEY— Numeric bot key used forX-Chutes-Bot-Key; must be divisible by8325468.SESSION_SECRETCHUTES_IDP_CLIENT_IDCHUTES_IDP_CLIENT_SECRETCHUTES_IDP_REDIRECT_URINEXT_PUBLIC_APP_URL
Optional:
SANDY_AGENT_MODELANTHROPIC_PROXY_PUBLIC_BASE_URLANTHROPIC_PROXY_INTERNAL_BASE_URLANTHROPIC_PROXY_ALLOWED_BOT_KEYSANTHROPIC_PROXY_ALLOWED_SOURCE_IPSANTHROPIC_PROXY_WINDOW_MSANTHROPIC_PROXY_MAX_MESSAGES_PER_WINDOWANTHROPIC_PROXY_MAX_COUNT_TOKENS_PER_WINDOWANTHROPIC_PROXY_MAX_TOKENS_PER_BOT_KEYSANDBOX_ANTHROPIC_PROXY_AUTH_TOKENSANDBOX_ANTHROPIC_PROXY_TOKEN_TTL_MSSANDY_WARM_SANDBOX(falseto disable)SANDY_WARM_SANDBOX_TTL_MIN(default20)
Security note on API keys: The
CHUTES_API_KEYenv var on this system has extended admin rights and must NEVER be passed into Sandy sandboxes or exposed to the agent. TheSANDBOX_CHUTES_API_KEYis a separate, restricted key that only has standard user permissions. The agent inside the sandbox sees this restricted key as$CHUTES_API_KEY.
The agent reads curated files from data/:
data/knowledge-snippets/data/docs/data/source-code/data/articles/
Refresh the data by re-running the extraction workflow in ../chutes-knowledge/ and copying outputs into this repo's data/ folder.
The agent includes a Discord bot that is currently restricted to Chutes Team #bot-chat. It uses Claude Opus 4.6 through the internal Anthropic-compatible proxy and does not call Anthropic directly from the sandbox. See DISCORD-BOT.md for full documentation.
Architecture notes, diagrams, and testing/stability guardrails live in docs2/.