API Reference

The Deep Research Assistant exposes a REST API (FastAPI) for creating, inspecting, and managing research runs. The current implementation is strict about governance for API-driven runs: required approval gates pause execution, decisions are persisted, and interrupted runs resume from durable checkpoints.

Base URL

http://localhost:8080/v1

End-to-End Demo

The example below shows a complete curl-driven deep research run, including strict approval handling, progress inspection, file-backed run logs, and final export.

1. Start the API server with Exa enabled

export DEEP_RESEARCH_EXA_API_KEY="your-exa-key"
export DEEP_RESEARCH_APPROVALS__MODE="strict"

2. Create a deep research run

curl \
  -X POST "http://localhost:8080/v1/research-runs" \
  -H "Content-Type: application/json" \
  -d '{
    "objective": {
      "title": "ADK tool governance deep research demo",
      "primary_question": "How should a Google ADK-based research assistant govern tool usage safely in an enterprise environment?",
      "decision_to_support": "Choose runtime guardrails for production rollout",
      "intended_audience": ["platform engineering", "security architecture"],
      "output_type": "technical_report",
      "desired_depth": "deep"
    },
    "tenant_id": "demo",
    "user_id": "architect-01",
    "mode": "review_first"
  }'

Example response:

{
  "run_id": "071521de",
  "status": "queued"
}

Save the run_id for the remaining calls:

RUN_ID=071521de

3. Poll current status

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID"

In strict mode, the run may pause like this:

{
  "run_id": "071521de",
  "status": "awaiting_approval"
}

4. Inspect the pending gate

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/approvals"

5. Approve the gate and resume execution

Approve Gate A:

curl \
  -X POST "http://localhost:8080/v1/research-runs/$RUN_ID/approvals/A" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "approved",
    "rationale": "Scope and risk framing look correct",
    "approver_id": "architect-01"
  }'

If the run later pauses at Gate B, C, or D, use the same pattern with /approvals/B, /approvals/C, or /approvals/D.

6. Check progress, frontier, and research graph

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/progress"

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/frontier"

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/graph"

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/concept-map"

7. Retrieve file-backed logs for this run

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/logs"

Or fetch only the most recent records:

curl \
  "http://localhost:8080/v1/research-runs/$RUN_ID/logs?limit=50"

The log records are filtered by run_id, so you can reconstruct what happened for one research run without scanning unrelated server output.

8. Stream live workflow events

curl \
  -N "http://localhost:8080/v1/research-runs/$RUN_ID/events"

9. Export the final report

curl \
  -X POST "http://localhost:8080/v1/research-runs/$RUN_ID/exports?format=markdown"

10. Optional: submit an intervention mid-run

curl \
  -X POST "http://localhost:8080/v1/research-runs/$RUN_ID/interventions" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "add_question",
    "instruction": "What concrete guardrails should apply to tool calls that access external systems?"
  }'

Endpoints

Research Runs

Create Research Run

POST /v1/research-runs
{
  "objective": {
    "title": "Secure agent runtime analysis",
    "primary_question": "Which architectural controls are required for a secure enterprise agent runtime?",
    "decision_to_support": "Define platform architecture"
  },
  "tenant_id": "acme",
  "user_id": "architect-01",
  "mode": "review_first",
  "constraints": {
    "minimum_primary_source_ratio": 0.6,
    "maximum_cost": 50
  }
}

Inspect Research Run

GET /v1/research-runs/{run_id}

Returns the full research run aggregate with all nested entities. Current implementation returns summary status, objective/scope, counts, and a report preview, plus runtime statuses such as queued, running, awaiting_approval, interrupted, completed, and failed.

Get Research Graph

GET /v1/research-runs/{run_id}/graph

Returns the concept map projection: topics, questions, claims, and their relationships. Currently returns run metadata plus claims and sources. Use /concept-map for the projected topic graph.

Get Research Frontier

GET /v1/research-runs/{run_id}/frontier

Returns open, resolved, and blocked questions with priorities and dependency edges. Currently returns the current question list and priority map.

Get Progress

GET /v1/research-runs/{run_id}/progress

Returns current phase, budget consumption, and completion estimates. When a required gate pauses execution, progress reflects the awaiting_approval phase until a decision is submitted.

Stream Events

GET /v1/research-runs/{run_id}/events

SSE stream of workflow events: run.started, perspective.created, claim.created, verification.passed, etc. The event stream is operational/live UX state. The same governance-significant events are also written into the durable audit log internally.

Get Run Logs

GET /v1/research-runs/{run_id}/logs

Returns file-backed JSON log records filtered by run_id. Use the optional limit query parameter to cap the number of returned records.

Interventions

Apply Intervention

POST /v1/research-runs/{run_id}/interventions
{
  "type": "challenge_claim",
  "target_id": "C-104",
  "instruction": "Find independent evidence that contradicts this claim."
}

Supported intervention types:

  • add_question โ€” add a new research question
  • challenge_claim โ€” trigger counter-evidence search
  • add_topic / remove_topic โ€” queue a scope change
  • add_perspective โ€” queue a new perspective
  • change_budget โ€” queue a budget change

Approvals

Get Pending Approvals

GET /v1/research-runs/{run_id}/approvals

Decide Approval

POST /v1/research-runs/{run_id}/approvals/{approval_id}
{
  "decision": "approved",
  "rationale": "Scope and risk assessment look correct"
}

Approval gates:

  • Gate A โ€” Scope: triggered for high-risk or ambiguous requests
  • Gate B โ€” Research Plan: perspectives, questions, budget
  • Gate C โ€” Evidence & Outline: claims, contradictions, proposed structure
  • Gate D โ€” Publication: required for external distribution

Behavior notes:

  • API-created runs enforce approvals by default.
  • In strict mode, a required gate moves the run into awaiting_approval.
  • Submitting an approval decision persists the decision and requeues the run from the latest durable checkpoint.
  • A development auto_approve mode exists behind configuration for local/test workflows.

Export

POST /v1/research-runs/{run_id}/exports
{
  "format": "markdown"
}

Current implementation returns the generated report body and echoes the requested format. Dedicated HTML/JSON/evidence-package rendering is not implemented yet.

Response Model

Most endpoints currently return plain JSON objects rather than a shared response envelope.

{
  "run_id": "run-001",
  "status": "awaiting_approval"
}

Events

The SSE event stream emits typed events at each workflow stage:

EventPayload
run.started{run_id, objective_title}
scope.proposed{scope, risk_level}
approval.requested{gate, display_data}
approval.decided{approval_id, status, rationale}
perspective.created{perspective_count}
question.created{question_count}
query.executed{query, results_count}
source.accepted{sources, accepted, rejected}
evidence.extracted{fragments}
claim.created{claims_created}
contradiction.detected{contradictions}
coverage.updated{coverage_metrics}
outline.proposed{section_count}
section.generated{section_title}
verification.passed{findings}
verification.failed{blocking_findings}
checkpoint.created{checkpoint_id, node}
checkpoint.restored{checkpoint_id, node_name}
run.resumed{checkpoint_id}
run.completed{report_length}