# Bike4Mind > An AI workspace: notebooks (sessions) over many LLM providers, files and data > lakes, artifacts, and agents. Bike4Mind is open source and self-hostable. Every path below is root-relative, so resolve it against the origin you fetched this file from. That keeps the file correct for bike4mind.com and for any self-hosted deployment. ## Agents - [The Open Door](/api/agent-quest/manifest): `agent-quest` - an onboarding quest built for agents rather than for people. Read the manifest, speak MCP, out-think a scheduling puzzle, make something, and sign the Wall of Agents. Completing it earns a free credit grant and a verifiable badge. Steps carry a `status`; only an `available` step has an `endpoint` to call. Also served over MCP as `b4m://agent-quest`. ## Authentication - Send an API key as `Authorization: Bearer ` on every HTTP API request. The `X-API-Key` header is still accepted but is the legacy form. - Read the key from the environment variable `B4M_API_KEY`. The MCP server reads the same variable, plus `B4M_API_URL` for the deployment origin. - A user creates a key in the web app under Profile > API Keys, at `/profile?tab=api-keys`. Ask for the narrowest scopes the task needs. - Never ask the user to paste a key into a chat, and never print, log, or commit one. If `B4M_API_KEY` is unset, tell the user to create a key and export it. - Some routes are not in the contract yet. If one you need is missing, say so rather than guessing its shape. ## Grounded answer To answer from a data lake's files, the key needs `datalake:read`, `notebooks:write` and `ai:chat`. Four calls: 1. `GET /api/v1/data-lakes`: pick a lake `id`. Paginated: pass `next_cursor` back as `cursor` until it is `null`. 2. `POST /api/v1/sessions` with `{"name", "dataLakeId"}`: keep the response `id`. `dataLakeId` already turns on forced retrieval, so do not send `forceKnowledgeRetrieval`. 3. `POST /api/chat` with `{"sessionId", "message"}`: read `tracking_info.quest_id` from the reply. 4. Poll `GET /api/v1/quests/{quest_id}` while `status` is `pending` or `running`; stop at `done` or `stopped`. - Check for failure before reading the answer: `type: "error"` (with `errorCode` when classified) or a `stopped` status is a failed turn. A run that died part-way still polls back as `done`, with `promptMeta.finishReason` set to `timeout` or `abandoned`: treat that text as partial. - Read `reply`: the visible answer, with `...` blocks and any trailing choices block already removed. It is `null` only while the turn has not written anything yet (`pending`/`running`). `replies[]` is the raw stored slots; you do not need it. - Polling does not use the daily key quota. - Request and response shapes: the [API reference](/api/v1/docs). ## API - [OpenAPI contract](/api/v1/openapi.json): the machine-readable HTTP API. Served with the current deployment as its `servers` entry, so it is ready for SDK codegen. - [Deployment OpenAPI contract](/api/v1/openapi.deployment.json): the contract above plus the endpoints of any add-on packages this deployment mounts. Identical to it when there are none. - [API reference](/api/v1/docs): the same contract, rendered for reading. ## MCP Bike4Mind ships its own MCP server over stdio or loopback HTTP: ``` npx -y @bike4mind/cli@latest mcp serve ``` It exposes the Bike4Mind tools plus the resources `b4m://notebook/{id}`, `b4m://file/{id}`, `b4m://project/{id}`, `b4m://artifact/{id}`, and `b4m://agent-quest`. Every resource except `b4m://agent-quest` needs credentials; the quest manifest is deliberately readable without them.