| name | quaid-research |
| description | Resolve knowledge gaps: fetch unresolved gaps, assess sensitivity, generate research
queries, ingest findings, and close gaps with a resolution slug.
|
| min_binary_version | 0.3.0 |
Research Skill
Overview
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.
memory_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 memory_gap_approve as a CLI command — route escalation through
your session's approval mechanism.
Sensitivity Levels
| Level | Meaning | Research Allowed |
|---|
internal | Brain-internal search only | quaid query + quaid 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.
Workflow
Step 1 — Fetch unresolved gaps
quaid gaps --limit 10 --json
Returns the ten highest-priority unresolved gaps. Each gap object contains:
id — numeric gap identifier
query_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 logged
sensitivity — internal / external / redacted
created_at
Step 2 — Assess each gap
For each gap:
-
Is it already answerable? Run quaid query "<query_text>" --json or
quaid 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.
Step 3a — Internal-only research
Use brain-internal commands only:
quaid query "<query_text>" --limit 10 --json
quaid search "<keyword>" --json
quaid 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.
Step 3b — External research (approved)
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:
Step 3c — Redacted external research
Sensitivity is external but entity names must be stripped before sending the query
externally. Construct a redacted query:
- Take
gap.query_text (or derive from gap.context if query_text is null).
- Replace all proper nouns, company names, and person names with generic placeholders:
<COMPANY>, <PERSON>, <PRODUCT>.
- Send the redacted query to Exa as in Step 3b.
- Store results with
source = "exa_redacted".
Step 4 — Ingest findings
Use the ingest skill to add findings to the brain. Two patterns:
Pattern A — Write a new page:
quaid put research/<gap_id>-findings < findings.md
Pattern B — Update an existing page:
quaid get <target_slug> --json
quaid 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.
Step 5 — Mark gap resolved
Once findings are ingested and a resolution page/slug exists:
-
Resolve the gap with the page that answers it (resolution is brain-internal
and needs no approval — approval workflows only gate sensitivity escalation):
quaid gaps resolve <gap_id> <resolution_slug>
quaid call memory_gap_resolve '{"id": <gap_id>, "slug": "<resolution_slug>"}'
The slug must resolve to an existing page; unknown gap ids return a
not-found error.
-
Confirm the gap appears in resolved state:
quaid gaps --resolved --json | jq '.[] | select(.id == <gap_id>)'
Gap Prioritisation Heuristics
When deciding which gaps to research first:
- Gaps referenced in pages with high inbound link counts (check
quaid graph).
- Gaps with
context that mentions blocking work or decisions.
- Gaps that are oldest (largest time since
created_at).
- Gaps with
external sensitivity (already approved — no additional friction).
Research Query Generation
When query_text is vague or too short to search effectively, expand it:
- Take the gap's
context field.
- Run
quaid query "<context>" --json to identify related pages.
- Use the titles and summaries of related pages to construct specific sub-queries.
- Break compound questions into individual factual questions (one query per unknown).
Rate Limiting Guidance
| 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 memory_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 memory_raw before extracting facts. This ensures
idempotent re-extraction if the extraction logic improves later.
Failure Modes
| Condition | Behaviour |
|---|
quaid 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 |
memory_raw returns -32001 (slug not found) | Create target page first, then retry memory_raw |
memory_put returns ConflictError | Re-fetch page (quaid get <slug> --json), merge changes, retry with new version |
| Approval for gap escalation is denied | Keep gap as internal; continue with internal-only research |