Resolve knowledge gaps: fetch unresolved gaps, assess sensitivity, generate research queries, ingest findings, and close gaps with a resolution slug.
The research skill provides a structured workflow for closing knowledge gaps logged in
the brain. Gaps are created with sensitivity = 'internal' by default. External research
requires an explicit approval step before any queries leave the local brain.
brain_gap_approve is an approval workflow dependency, not a binary command.
It represents a human or policy decision to escalate a gap's sensitivity from internal
to external or redacted. That approval may be granted by the user confirming in
their MCP client, a team policy workflow, or a future MCP tool when implemented.
Do not attempt to call brain_gap_approve as a CLI command — route escalation through
your session's approval mechanism.
| Level | Meaning | Research Allowed |
|---|---|---|
internal| Brain-internal search only |
gbrain query + gbrain search |
external | Approved for web/API search | Exa, Crustdata, public APIs |
redacted | External-approved but entity names stripped | Exa with anonymised query |
All gaps start as internal. Escalation to external or redacted requires approval.
gbrain gaps --limit 10 --json
Returns the ten highest-priority unresolved gaps. Each gap object contains:
id — numeric gap identifierquery_text — the original question (may be null if sensitivity is redacted)query_hash — SHA-256 of query (always present)context — additional context provided when the gap was loggedsensitivity — internal / external / redactedcreated_atFor each gap:
Is it already answerable? Run gbrain query "<query_text>" --json or
gbrain search "<keywords>" --json. If top result answers the question with
confidence, proceed to Step 5 (resolve) without external research.
What is the sensitivity?
internal → proceed to Step 3a.external → proceed to Step 3b.redacted → proceed to Step 3c.Does it need priority escalation? If the gap has high strategic importance
(referenced by many pages, mentioned in a page with many inbound links), consider
requesting approval to escalate to external.
Use brain-internal commands only:
gbrain query "<query_text>" --limit 10 --json
gbrain search "<keyword>" --json
gbrain graph <related_slug> --depth 2 --json
Synthesise findings from results. If findings are sufficient, go to Step 4. If not, and the gap warrants external research, request approval to escalate.
Only execute after the gap's sensitivity has been confirmed as external through
the approval workflow.
Exa integration pattern:
query = gap.query_text
POST https://api.exa.ai/search
Body: {"query": "<query>", "numResults": 5, "useAutoprompt": true}
Headers: {"x-api-key": "<EXA_API_KEY>"}
For each result:
POST https://api.exa.ai/contents with result IDsbrain_raw:
gbrain call brain_raw '{"slug":"<target_slug>","source":"exa","data":<raw_json>}'
Sensitivity is external but entity names must be stripped before sending the query
externally. Construct a redacted query:
gap.query_text (or derive from gap.context if query_text is null).<COMPANY>, <PERSON>, <PRODUCT>.source = "exa_redacted".Use the ingest skill to add findings to the brain. Two patterns:
Pattern A — Write a new page:
gbrain put research/<gap_id>-findings < findings.md
Pattern B — Update an existing page:
gbrain get <target_slug> --json # fetch current version
# Edit compiled_truth with findings
# Append to timeline with source and date
gbrain put <target_slug> --expected-version <N> < updated_page.md
Always append to the timeline section with a sourced, dated entry. Never overwrite
compiled_truth directly with raw external content — extract structured facts first.
Once findings are ingested and a resolution page/slug exists:
Obtain approval through the session's brain_gap_approve workflow, providing:
gap_idresolution_slug — the slug of the page containing the answerAfter approval is granted, confirm the gap appears in resolved state:
gbrain gaps --resolved true --json | jq '.[] | select(.id == <gap_id>)'
When deciding which gaps to research first:
gbrain graph).context that mentions blocking work or decisions.created_at).external sensitivity (already approved — no additional friction).When query_text is vague or too short to search effectively, expand it:
context field.gbrain query "<context>" --json to identify related pages.| Source | Rate Limit | Guidance |
|---|---|---|
| Exa | 20 req/min (free tier) | Batch at most 10 gaps per session |
| Crustdata | Varies by tier | Store full API response in brain_raw first; extract facts second |
| GitHub API | 60 req/hr (unauthenticated) | Use authenticated token for upgrade skill integration |
Always store the raw API response in brain_raw before extracting facts. This ensures
idempotent re-extraction if the extraction logic improves later.
| Condition | Behaviour |
|---|---|
gbrain gaps returns empty | Log: "No unresolved gaps. Nothing to research." |
| Exa API returns 429 | Wait 60s and retry once; if still 429, skip gap and log warning |
brain_raw returns -32001 (slug not found) | Create target page first, then retry brain_raw |
brain_put returns ConflictError | Re-fetch page (gbrain get <slug> --json), merge changes, retry with new version |
| Approval for gap escalation is denied | Keep gap as internal; continue with internal-only research |