Research
POST /v1/research — single tuned multi-round web research with citations.
POST /v1/research runs an iterative agent: it plans follow-up searches, scrapes top sources, ranks chunks by relevance, and synthesises a cited answer. Returns synchronously in roughly 30–90 seconds.
There is no quick/deep selector and no rounds knob — Brime runs a single tuned flow with sensible defaults (5 rounds max, a production-grade synthesis model). Streaming is optional via SSE.
Quick example
from brime import Brime
client = Brime(timeout=180)
result = client.research(query="what are the 2025 EU AI Act compliance deadlines")
print(result.answer)
print(f"Sources: {len(result.sources)}")import { Brime } from "@brime-ai/brime";
const client = new Brime({ timeout: 180_000 });
const result = await client.research({
query: "what are the 2025 EU AI Act compliance deadlines",
});
console.log(result.answer);
console.log(`Sources: ${result.sources.length}`);curl https://api.brime.dev/v1/research \
-H "Authorization: Bearer $BRIME_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "query": "what are the 2025 EU AI Act compliance deadlines" }'Request
| Field | Type | Default | Description |
|---|---|---|---|
query | string | required | Research question (1–1,000 chars). |
topic | "general" | "news" | "finance" | "general" | Recency hint. |
max_results | integer | 5 | 1–20. Sources per round. |
time_range | "day" | "week" | "month" | "year" | — | Recency window. |
stream | bool | false | Return SSE stream instead of single JSON. |
model | string | server default | Whitelist override (advanced). |
Other historical fields (depth, max_rounds, fast, scrape, query_gen, token_mode) are accepted but ignored — the tuned flow handles those internally.
Response
{
"query": "what are the 2025 EU AI Act compliance deadlines",
"answer": "The ECB held rates at 3.25% in October 2025, signalling a pause through year-end...",
"sources": [
{
"title": "2025 ECB Rate Decision — Reuters",
"url": "https://en.wikipedia.org/wiki/Generative_artificial_intelligence",
"content": "...",
"score": 0.94,
"published_date": null
}
],
"steps": [
{ "round": 1, "queries": ["ECB October 2025 rate decision"], "result_count": 9 }
],
"request_id": "req_01J...",
"credits_used": 5,
"latency_ms": 48230
}| Field | Type | Notes |
|---|---|---|
query | string | Echoes the request. |
answer | string | Synthesised answer with inline citations. |
sources | ResearchSource[] | Relevance-ranked top-k aggregate across rounds. |
steps | object[] | Per-round trace. |
request_id | string | |
credits_used | number | 5 credits flat. |
latency_ms | number | Wall-clock. |
Streaming (SSE)
Pass Accept: text/event-stream (or use client.researchStream / stream: true body field) to receive a live event for each step:
event: intent
data: {"query": "..."}
event: tool_call
data: {"round": 1, "queries": ["ECB October 2025 rate decision"]}
event: tool_result
data: {"round": 1, "result_count": 9}
event: sources
data: {"sources": [...]}
event: final
data: {"answer": "...", "sources": [...]}
event: done
data: {}See Status & streaming for the full event vocabulary and resume semantics.
Edge cases
- Empty SERP for all rounds: returns a "no reliable sources" answer with empty
sources. - Iteration cap hit (model wants more rounds than budget): synthesises with what was gathered.
- Connection drop during SSE: reconnect with
Last-Event-IDto resume.
Errors
| Status | code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed body or empty query. |
| 401 | unauthorized | Missing/revoked API key. |
| 429 | rate_limited | Per-key budget hit. |
| 502 | upstream_error | LLM, SERP, or extract layer degraded. |
See Errors for the full catalog and retry guidance.