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 skill
npx skills add https://kbdrop.io --global

Setup

Three steps to the first answer

  1. Prepare a knowledge base

    Add files, a ZIP, or a website in the browser, or create one with kb-drop knowledge-bases create or the management API. Wait until it is ready.

  2. Check CLI authentication

    Use Node.js 24 or newer. Run npx @kbdrop/cli@latest auth status --json and read data.authenticated and data.source. Exit 0 also occurs when logged out. An existing environment API key takes precedence over saved OAuth.

  3. 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" \
  --json

Direct 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.json

Response

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

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/ \
  --json

Production notes

  • Prefer OAuth for people; keep CI keys only in secret storage.
  • Honor Retry-After and preserve one idempotency key.
  • Store the returned conversation ID to continue a thread.
  • Keep JSON Pointer claim citations with structured fields.
Review the security boundary