Developer quickstart
Get one compact, cited answer from your knowledge base.
Query a kbDrop knowledge base with the OAuth CLI or JSON API and receive one compact, cited completion; opt into server-sent events only when streaming is useful.
Agent-native
Give your agent the safe workflow
The open Agent Skill teaches compatible harnesses to prefer the OAuth CLI, compact JSON, stable citations, and secret-safe input.
Inspect the official skillnpx skills add https://kbdrop.io --globalSetup
Three steps to the first answer
Prepare a knowledge base
Add files, a ZIP, or a website in the browser, or create one with
kb-drop knowledge-bases createor the management API. Wait until it is ready.Check CLI authentication
Use Node.js 24 or newer. Run
npx @kbdrop/cli@latest auth status --jsonand readdata.authenticatedanddata.source. Exit 0 also occurs when logged out. An existing environment API key takes precedence over saved OAuth.Read one completed JSON result
The default response is the authoritative completion with compact citations. No event-stream parser is required.
Sign in when credentials are missing
If data.authenticated is false, run npx @kbdrop/cli@latest auth login and complete browser sign-in and consent. On a remote terminal, use auth login --device --no-browser and open the displayed URL on another device.
Both flows need an unlocked macOS Keychain, Windows Credential Manager, or Linux Secret Service. Device login still needs that store. If the CLI reports keychain_unavailable, configure the native store or use an existing KB_DROP_API_KEY injected by a secret manager. Repeating login cannot supply a missing keychain. A plain login can read and query; creating knowledge bases needs auth login --manage, which the account owner approves on the consent screen. Keep tokens and keys out of chat and shell commands.
Recommended
Authenticate and ask with the CLI
Set KB_DROP_KNOWLEDGE_BASE_ID to the ID from your knowledge base's Developers tab. Save your question in question.txt with an editor. File input keeps its contents out of shell history and process arguments; piping a literal question through printf still records that literal in the shell command.
Generate and save a request ID once for each new question. If a response is lost, rerun only ask with that saved ID and unchanged input/options. Restore the saved ID in a new shell. Without --idempotency-key, a new invocation can create another turn. After bounded retries fail, retain the ID and report the error; do not generate a new ID to bypass a failure.
Once per new question:
export KB_DROP_REQUEST_ID="$(node -p 'crypto.randomUUID()')"Run, or resume with the saved ID:
npx @kbdrop/cli@latest ask \
--knowledge-base "$KB_DROP_KNOWLEDGE_BASE_ID" \
--input-file ./question.txt \
--idempotency-key "$KB_DROP_REQUEST_ID" \
--jsonDirect API
Or POST a JSON question
Server and CI callers can use an API key from the switchboard on your home page. /v1/messages answers from every knowledge base plugged into the key, and each citation names its knowledge base; /v1/knowledge-bases/<id>/messages asks one of them. Omit Accept and stream for buffered JSON; response controls can add excerpts, usage, latency, or a strict structured-output schema. A knowledge base the key can't reach returns 401 invalid_api_key without revealing tenant data.
Supply authorization.headers through a secret manager and prepare message.json in an editor with the input and a saved idempotency_key. The complete contract includes request fields, structured-output constraints, search filters, errors, and recovery rules.
curl --fail-with-body --request POST \
--url 'https://kbdrop.io/v1/messages' \
--header @./authorization.headers \
--header 'Content-Type: application/json' \
--data-binary @./message.jsonResponse
Use the authoritative completion
Compact citations include permission-safe canonical/deep links and human locators. Request text/event-stream or set stream: true only for incremental deltas; the existing ordered SSE contract remains supported and its finalresponse.completed event is authoritative.
{
"type": "response.completed",
"request_id": "...",
"operation_id": "...",
"conversation_id": "...",
"knowledge_base_id": null,
"interface_id": "...",
"knowledge_base_ids": ["...", "..."],
"answer": "Hold reset for ten seconds [S1].",
"citations": [{
"id": "S1",
"source_id": "...",
"display_title": "Reset guide",
"source_url": null,
"deep_link": "https://kbdrop.io/v1/knowledge-bases/.../sources/...?chunk_id=...",
"locator": { "pages": [12] },
"locator_text": "page 12",
"knowledge_base": { "id": "...", "name": "Handbook" }
}],
"insufficient_evidence": false
}Evidence search
Get ranked evidence without an answer model
Code results preserve paths, symbols, and line locations, and an empty result explains why no evidence qualified.
Save your query in query.txt. Repeat --language for multiple languages; use --path-prefix at most once. For multiple subtrees, choose a common prefix or make separate searches.
npx @kbdrop/cli@latest search \
--knowledge-base "$KB_DROP_KNOWLEDGE_BASE_ID" \
--input-file ./query.txt \
--language typescript --language javascript \
--path-prefix src/ \
--jsonProduction notes
- Prefer OAuth for people; keep CI keys only in secret storage.
- Honor
Retry-Afterand preserve one idempotency key. - Store the returned conversation ID to continue a thread.
- Keep JSON Pointer claim citations with structured fields.