Research

May 14, 2026 · View on GitHub

← Docs index

Fusion Research is a cited search-and-synthesis pipeline: create bounded research runs, gather sources with built-in web tools, and synthesize findings into actionable task context from the dashboard, CLI, or agent sessions.

Execution model (FN-4221)

All Fusion surfaces use one execution model:

  • Dashboard, CLI, pi extension, and engine agent tools enqueue runs through ResearchStore.createRun(...).
  • The engine is the only execution dispatcher. ProjectEngine owns a single shared ResearchOrchestrator, and ResearchRunDispatcher polls queued runs and calls ResearchOrchestrator.startRun(...).
  • Surfaces do not construct ad-hoc orchestrators.

If no engine is running, enqueue still succeeds but the run remains queued until an engine starts and the dispatcher picks it up. CLI --wait and pi-extension wait_for_completion poll persisted status and return a timeout/no-progress message that explicitly calls out this engine requirement.


Not pi-autoresearch: Fusion Research is a cited search/synthesis pipeline. The autonomous try-measure-keep-revert loop from upstream pi-autoresearch is a separate domain (experiment sessions); see naming-decision-2026-05.md.

Overview

A research run is a persisted workflow that moves through orchestration phases:

planning → searching → fetching → synthesizing → finalizing

Each run produces:

  • Findings — structured results with headings, content, and source citations
  • Citations — referenced URLs and sources
  • Summary — synthesized output combining all discovered information
  • Events — timestamped lifecycle log for auditability

Runs are persisted in the project database and can be listed, searched, exported, and converted into tasks.

When to use Research

  • Explore a technology, library, or API before writing implementation tasks
  • Compare approaches (e.g., "SQLite WAL vs rollback journal") with cited sources
  • Gather context from web search, GitHub, and local docs in a single structured run
  • Let AI agents supplement task planning with real-time information

Research is not a replacement for reading source code or local docs — use it when repository-local context is insufficient for the question at hand.


Prerequisites

Research requires the experimental feature flag. Web search works out of the box using built-in agent tools, and external provider setup is optional advanced configuration.

1. Enable the feature flag

The Research view is gated behind an experimental feature flag. Set in global settings:

{
  "experimentalFeatures": {
    "researchView": true
  }
}

This also reveals the Research Defaults and Research settings sections in the dashboard Settings modal, and enables agent/CLI research tools (fn_research_*).

2. Built-in web search is the default

By default, researchGlobalWebSearchProvider resolves to "builtin". Search and fetch run through the agent runtime's native WebSearch and WebFetch tools, so no API key is required for baseline usage, and web search stays enabled even if older persisted settings still contain enabledSources.webSearch: false.

3. Optional: external search backends

You can opt into external providers in global settings:

ProviderRequired settings
"builtin"No API key required (default)
"searxng"researchGlobalSearxngUrl — URL of your SearXNG instance
"brave"researchGlobalBraveApiKey — Brave Search API key
"google"researchGlobalGoogleSearchApiKey + researchGlobalGoogleSearchCx — Google Custom Search credentials
"tavily"researchGlobalTavilyApiKey — Tavily API key

API keys are stored through Fusion's auth credential pipeline (/api/auth/api-key), not in settings JSON directly.

4. (Optional) Configure synthesis model

If LLM synthesis is enabled (default: on), set a synthesis provider and model:

{
  "researchGlobalDefaults": {
    "synthesisProvider": "anthropic",
    "synthesisModelId": "claude-sonnet-4-5"
  }
}

If no synthesis model is configured, Research falls back to the global default model lane. If no global default model is resolvable, synthesis may fail with a PROVIDER_UNAVAILABLE error.

Settings hierarchy

Research settings resolve through resolveResearchSettings() with this precedence:

  1. Project override (researchSettings.*)
  2. Global default (researchGlobalDefaults.*)
  3. Hardcoded fallback defaults

See Settings Reference → Research for the complete key listing.


Dashboard Usage

The Research view is accessible from:

  • Desktop: Header → More views overflow menu → Research
  • Mobile: More sheet in the mobile navigation bar

Research is intentionally not shown in the primary board/list/agents/missions/chat toggle row.

Creating a run

  1. Open the Research view
  2. Enter your query in the text area
  3. Select which providers to use (Web Search, Page Fetch, GitHub, Local Docs, LLM Synthesis)
  4. Click Create Run

The run enters the queued status. Depending on entrypoint, execution may start immediately or wait for an execution surface/engine path to pick it up.

Viewing results

Select a run from the history sidebar to see:

  • Status dot and label — current run status
  • Summary — synthesized overview
  • Findings — individual structured results, each with a heading and content
  • Citations — linked source URLs
  • Run history — expandable event log (click "Run history")

Run lifecycle controls

ActionDescription
CancelRequests cancellation for an active run
RetryCreates a new retry run from a failed/cancelled/timed-out run
RefreshReloads run data from the server
Export MDDownloads results as a Markdown file
Export JSONDownloads results as a JSON file
Export HTMLDownloads results as an HTML file

Converting findings to tasks

Each finding has two task-facing actions:

  • Create Task — Opens a modal to create a new task from the finding, with pre-populated title, description, and priority. The finding content is attached as a task document (key: research-{runId}) and optionally as a Markdown attachment.
  • Enrich Task — Attaches the finding content to an existing task as a document and/or attachment.

Status indicators

StatusMeaning
queuedRun created, waiting for engine pickup
runningActively executing orchestration phases
cancellingCancellation requested, waiting for graceful shutdown
retry_waitingRetry run created, waiting to re-enter the queue
completedRun finished successfully with results
failedRun encountered an unrecoverable error
cancelledRun was cancelled by user
timed_outRun exceeded the configured duration limit
retry_exhaustedAll retry attempts exhausted

CLI Usage

The fn research command provides cited-research run management from the terminal (search/fetch/synthesis runs, not experiment sessions).

Commands

# Create a research run
fn research create --query "Compare sqlite WAL vs rollback journal"

# Create and wait for completion (up to 90 seconds)
fn research create --query "Rust async runtime trade-offs" --wait --max-wait-ms 120000

# List recent runs
fn research list
fn research list --status failed --limit 20

# Show run details
fn research show RR-001

# Export run results
fn research export RR-001 --format json --output ./artifacts/research-RR-001.json
fn research export RR-001 --format markdown

# Cancel an active run
fn research cancel RR-001

# Retry a failed run
fn research retry RR-001 --json

All commands support --json for machine-readable output.

Error codes

CodeMeaningRecovery
FEATURE_DISABLEDResearch is disabled in settingsEnable project or global research settings
MISSING_CREDENTIALSNo API key for the configured providerAdd provider credentials in Settings
PROVIDER_UNAVAILABLENo configured provider or provider downConfigure a search provider
RATE_LIMITEDProvider rate limit hitRetry after cooldown period
PROVIDER_TIMEOUTProvider request timed outIncrease timeout or retry
RUN_CANCELLEDRun was cancelled by userRetry if needed
RETRY_EXHAUSTEDAll retry attempts usedCreate a new run
INVALID_TRANSITIONIllegal status changeCheck current run status
NON_RETRYABLE_PROVIDER_ERRORProvider returned a permanent errorCheck provider configuration
INTERNAL_ERRORUnexpected internal errorCheck engine logs

See CLI Reference → fn research for the full command reference.


API Reference

All research endpoints are under /api/research. The router is registered in packages/dashboard/src/routes/register-integrated-routers.ts.

Runs

MethodPathDescription
GET/research/runsList runs (query params: status, q, limit)
POST/research/runsCreate a new run (body: query, providers, etc.)
GET/research/runs/:idGet run details with findings and citations
PATCH/research/runs/:idUpdate run fields
DELETE/research/runs/:idDelete a run
POST/research/runs/:id/cancelRequest cancellation
POST/research/runs/:id/retryCreate a retry run
PATCH/research/runs/:id/statusUpdate run status
POST/research/runs/:id/eventsAppend an event
POST/research/runs/:id/sourcesAdd a source
PATCH/research/runs/:id/sources/:sourceIdUpdate a source
PUT/research/runs/:id/resultsSet run results

Exports

MethodPathDescription
GET/research/runs/:id/exportExport run (query param: format = markdown, json, html)
POST/research/runs/:id/exportsCreate an export record
GET/research/runs/:id/exportsList exports for a run
GET/research/exports/:exportIdDownload/get a specific persisted export

Note: CLI/core export formats and server export endpoint formats are intentionally not identical today. CLI/core accept pdf, while the server run export endpoint documents markdown, json, and html.

Task Integration

MethodPathDescription
POST/research/runs/:runId/findings/:findingId/taskCreate a task from a finding
POST/research/runs/:runId/findings/:findingId/tasks/:taskId/enrichAttach finding to existing task

Both endpoints support attachExport: boolean in the request body to include a Markdown attachment.

Search & Stats

MethodPathDescription
GET/research/search?q=<text>Full-text search across runs
GET/research/statsAggregate run counts by status

Availability

List and detail endpoints include an availability object:

{
  "available": true,
  "supportedProviders": ["web-search", "page-fetch", "github", "local-docs", "llm-synthesis"],
  "supportedExportFormats": ["markdown", "json", "html"]
}

When available is false, the response includes reason and setupInstructions fields for graceful degradation.


Agent Integration

AI agents (triage, executor, and custom roles) can use research tools during planning and execution sessions. These tools are registered in the pi extension (packages/cli/src/extension.ts).

Additionally, planning-mode sessions and the LLM synthesis agent can opt into runtime builtin WebSearch/WebFetch tools (when the selected runtime supports them), complementing configured research providers.

Available tools

ToolDescription
fn_research_runStart a bounded cited-research run (search/fetch/synthesis). Parameters: query, wait_for_completion, max_wait_ms
fn_research_listList recent cited-research runs. Parameters: status, limit
fn_research_getGet a cited-research run's structured findings. Parameters: id
fn_research_cancelCancel an active cited-research run. Parameters: id
fn_research_retryRetry a failed/timed-out cited-research run when retryable. Parameters: id

Tool responses

All tools return:

  • Text content — concise human-readable summary
  • Structured details — machine-readable metadata (runId, status, summary, findings, citations, error, setup)

ResearchFinding.confidence in this subsystem is synthesis-emitted confidence from the LLM provider (0–1), not a statistical confidence score.

Availability checks

Before creating runs, fn_research_run checks:

  1. Research is enabled in settings
  2. Web search is available ("builtin" by default, or an explicitly configured external backend)
  3. Required API keys are present for external providers

If a check fails, the tool returns an actionable error with setup guidance instead of crashing. In practice, with the default "builtin" backend, provider-setup errors are mostly limited to explicit external-provider selections.

Best practices for agents

  • Use research only when repository/local context is insufficient for the question
  • Keep queries narrow and task-scoped — avoid open-ended exploration
  • Persist durable conclusions with fn_task_document_write (e.g., key="research")
  • Check tool availability before relying on research in automated flows

See Agents → Research Tools for more details.


Storage

Research data is persisted in the project SQLite database (.fusion/fusion.db) using three tables:

research_runs

Primary table for research run state.

ColumnTypeDescription
idTEXT PKRun identifier (format: RR-{timestamp}-{random})
queryTEXT NOT NULLResearch query text
topicTEXTOptional topic/label
statusTEXTCurrent run status
projectIdTEXTOptional project scope
triggerTEXTOptional trigger source
providerConfigTEXT (JSON)Provider configuration used
sourcesTEXT (JSON)Array of research sources
eventsTEXT (JSON)Array of run events
resultsTEXT (JSON)Research results (findings, summary, citations)
errorTEXTError message if failed
tokenUsageTEXT (JSON)Token usage metrics
tagsTEXT (JSON)String array of tags
metadataTEXT (JSON)Arbitrary metadata
lifecycleTEXT (JSON)Lifecycle details (attempts, retry info, failure class)
createdAtTEXTISO timestamp
updatedAtTEXTISO timestamp
startedAtTEXTWhen execution began
completedAtTEXTWhen execution ended
cancelledAtTEXTWhen cancellation took effect

Indexes: status, createdAt, updatedAt, (projectId, trigger, status)

research_exports

Persisted export records.

ColumnTypeDescription
idTEXT PKExport identifier
runIdTEXT FK → research_runs(id)Parent run
formatTEXT NOT NULLExport format (json, markdown, pdf)
contentTEXT NOT NULLExport content
filePathTEXTOptional file path if saved to disk
createdAtTEXT NOT NULLISO timestamp

research_run_events

Append-only event log for run lifecycle tracking.

ColumnTypeDescription
idTEXT PKEvent identifier
runIdTEXT FK → research_runs(id)Parent run
seqINTEGER NOT NULLSequence number within run
typeTEXTEvent type (info, warning, error, progress, etc.)
messageTEXTHuman-readable message
statusTEXTRun status at event time
classificationTEXTFailure classification if applicable
metadataTEXT (JSON)Arbitrary metadata
createdAtTEXT NOT NULLISO timestamp

Index: (runId, seq) for ordered retrieval.

See Storage for the full storage architecture.


Architecture

The research subsystem spans four packages:

PackageModuleResponsibility
@fusion/coreresearch-store.tsRun CRUD, status transitions, event/source management, exports
@fusion/coreresearch-types.tsType definitions: statuses, events, sources, findings, orchestration
@fusion/coreresearch-settings.tsSettings resolution with project/global/fallback hierarchy
@fusion/engineresearch-orchestrator.tsPhase lifecycle management, concurrency control, cancellation
@fusion/engineresearch-step-runner.tsProvider execution: search, fetch, synthesis with timeout/abort
@fusion/engineresearch/Provider implementations and registry
@fusion/dashboardresearch-routes.tsExpress router for /api/research endpoints
@fusion/dashboardResearchView.tsxDashboard UI for research runs
@fusion/dashboardResearchTaskActionModal.tsxCreate/enrich task modal for findings
@runfusion/fusioncommands/research.tsCLI subcommands for research management
@runfusion/fusionextension.tsAgent tool definitions for research

Orchestration phases

planning → searching → fetching → synthesizing → finalizing → completed
  1. Planning — Validates configuration and creates an execution plan
  2. Searching — Queries configured providers for relevant sources
  3. Fetching — Retrieves full content for discovered sources
  4. Synthesizing — Runs LLM synthesis over fetched content (configurable rounds)
  5. Finalizing — Writes structured results (findings, summary, citations)

Each phase emits events (phase-changed, step-started, step-completed, step-failed) for real-time progress tracking.

Concurrency

Runs are processed through an AgentSemaphore with configurable maxConcurrentRuns (default: 3). The engine processes pending runs from the queue as slots become available.

Retry behavior

Failed or timed-out runs can be retried. The system tracks:

  • Attempt count and max attempts (default: 3)
  • Root run ID — chains retries back to the original run
  • Failure class — determines retryability (retryable_transient vs non_retryable)

When all retries are exhausted, the run transitions to retry_exhausted.


Troubleshooting

SymptomCauseResolution
"Research is disabled in settings"researchGlobalEnabled or researchSettings.enabled is falseEnable in Settings → Research
"Research provider is not configured"External provider setup is incompleteSwitch back to builtin search or finish configuring your selected external provider in Settings
"Missing API key for {provider}"Auth credential not foundConfigure provider credentials in Settings → Authentication
Run stuck in queuedEngine not running or no available concurrency slotsStart the project engine; check maxConcurrentRuns
Run times outProvider slow or maxDurationMs too lowIncrease timeout in project research settings
All retries exhaustedPersistent provider errorCheck provider status; create a fresh run
Research view not visible in dashboardFeature flag disabledSet experimentalFeatures.researchView to true
Settings modal missing Research sectionsFeature flag disabledEnable researchView feature flag first