Skip to content

Commit be5ff72

Browse files
docs: match NeuroAPI timeouts and cut repeated prose
Use the documented client timeouts (60s sync, 120s structured output, no read timeout on streams) and drop invented numbers and duplicate explanations. Co-authored-by: Vlad Yashin <0xspacecreated@users.noreply.github.com>
1 parent f76c180 commit be5ff72

5 files changed

Lines changed: 136 additions & 239 deletions

File tree

‎skills/neurobro-catalyst-watch/SKILL.md‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ Authenticate with the `X-API-Key` header, reading the key from the
4747
`NEUROAPI_API_KEY` environment variable - never hardcode it. The body takes a
4848
`prompt` and a `mode` (`fast` | `smart` | `max`, default `smart`). A
4949
non-streaming run longer than 300 seconds returns `504` `agent_timeout`
50-
and is not billed, so set the client timeout above 300 seconds and prefer
51-
`stream: true` for `max`.
50+
and is not billed. Use `stream: true` for long runs, including `max`.
5251

5352
```bash
5453
curl -s https://api.neurobro.ai/api/v1/agent/ask \
@@ -199,7 +198,7 @@ def ask(prompt: str, mode: str = "smart") -> str:
199198
"https://api.neurobro.ai/api/v1/agent/ask",
200199
headers={"X-API-Key": os.environ["NEUROAPI_API_KEY"]},
201200
json={"prompt": prompt, "mode": mode},
202-
timeout=330,
201+
timeout=60,
203202
)
204203
res.raise_for_status()
205204
return res.json()["answer"]
@@ -236,7 +235,7 @@ inside the trading window.
236235
the plan; it reasons over expectations, positioning, and history together.
237236
- `max` - a watchlist-wide calendar across many assets, or a high-stakes event
238237
(a major earnings print, an FOMC decision) where the deepest reasoning pays.
239-
Stream it (`stream: true`); a non-streaming run is stopped at 300 seconds.
238+
Use `stream: true`.
240239
- `fast` - only for a quick "what events are coming" lookup with no analysis.
241240

242241
## Risk notes

‎skills/neurobro-market-research/SKILL.md‎

Lines changed: 60 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ curl -s https://api.neurobro.ai/api/v1/agent/ask \
2929

3030
## When to use this skill
3131

32-
- Researching a single stock or token (fundamentals, technicals, narrative).
33-
Equities include US listings and stocks in Indonesia, Brazil, and Vietnam
34-
(quotes, fundamentals, financials, technicals; a company name can be
35-
resolved to its ticker).
32+
- Researching a single stock or token (fundamentals, technicals, narrative),
33+
including Indonesia, Brazil, and Vietnam listings (quotes, fundamentals,
34+
financials, technicals, and company name to ticker)
3635
- Building bull/bear cases or trade setups
3736
- Comparing assets, sectors, or factors
3837
- Macro questions - rates, inflation, central-bank outlooks
@@ -76,7 +75,7 @@ curl -s https://api.neurobro.ai/api/v1/health \
7675
| --- | --- |
7776
| `X-API-Key` | `neuro_...` (required) |
7877
| `Content-Type` | `application/json` |
79-
| `Idempotency-Key` | Optional. 1-255 printable ASCII. Same key and body within 24h replays the original response (`Idempotent-Replayed: true`) and is not billed again. |
78+
| `Idempotency-Key` | Optional. 1-255 printable ASCII. Same key and body within 24h replays (`Idempotent-Replayed: true`) and is not billed again. |
8079

8180
Request body:
8281

@@ -94,15 +93,14 @@ Response (`stream=false`):
9493
```json
9594
{
9695
"answer": "The bull case for NVDA rests on ...",
97-
"output": null,
9896
"mode": "smart",
9997
"request_id": "8b3a2f0e-1d7e-4c6b-9b2a-f5e23a1c9d44",
10098
"usage": { "prompt_tokens": 124, "completion_tokens": 256, "cached_tokens": 80, "cost_units": 2 }
10199
}
102100
```
103101

104-
`request_id` is also the `X-Request-Id` header - quote it when reporting
105-
issues. With `output_schema`, read `output` (`answer` is `null`).
102+
`request_id` is also the `X-Request-Id` header. With `output_schema`, read
103+
`output` (`answer` is `null`).
106104

107105
## Choosing a mode
108106

@@ -139,10 +137,9 @@ curl -s https://api.neurobro.ai/api/v1/agent/ask \
139137

140138
### Follow-up questions (multi-turn)
141139

142-
The API is stateless. To ask a follow-up, replay prior turns in
143-
`message_history`. Roles the agent uses are `"user"` and `"assistant"`.
144-
`"system"`, `"developer"`, `"tool"`, and `"function"` are accepted and
145-
ignored; put instructions in `system_prompt`. Any other role returns `422`.
140+
The API is stateless. Replay prior turns in `message_history`. `"user"` and
141+
`"assistant"` reach the agent. `"system"`, `"developer"`, `"tool"`, and
142+
`"function"` are accepted and ignored. Any other role returns `422`.
146143

147144
```python
148145
import os, httpx
@@ -151,13 +148,11 @@ URL = "https://api.neurobro.ai/api/v1/agent/ask"
151148
HEADERS = {"X-API-Key": os.environ["NEUROAPI_API_KEY"]}
152149

153150
def ask(prompt: str, history: list[dict] | None = None, mode: str = "smart") -> dict:
154-
# Sync runs are stopped server-side at 300s (504 agent_timeout).
155-
# Sit above that so the 504 is returned. Prefer stream=True for max.
156151
res = httpx.post(
157152
URL,
158153
headers=HEADERS,
159154
json={"prompt": prompt, "mode": mode, "message_history": history or []},
160-
timeout=330,
155+
timeout=60,
161156
)
162157
res.raise_for_status()
163158
return res.json()
@@ -177,12 +172,13 @@ Persist the transcript on your side; trim the oldest turns once it gets long
177172

178173
### Streaming a long answer (SSE)
179174

180-
Pass `"stream": true` for deep `max` investigations, and for any run that
181-
might exceed 300 seconds. Each event is `{"type": "status_update" | "complete", "data": {"answer", "usage"}}`.
182-
Append `data.answer.chunk.content`. `data.answer` is `null` when the event
183-
has no text. `data.usage` arrives once near the end. The stream ends with
184-
`data: [DONE]`. An error event is `{"type":"error","message":"..."}` and
185-
has no `[DONE]`.
175+
Pass `"stream": true` for a long run, including `max`. A non-streaming run
176+
longer than 300 seconds returns `504` `agent_timeout` and is not billed.
177+
Each event is `{"type": "status_update" | "complete", "data": {"answer", "usage"}}`.
178+
Append `data.answer.chunk.content`. `data.answer` is `null` when that event
179+
has no text. `data.usage` arrives once, near the end. Success ends with
180+
`data: [DONE]`. On failure the last event is
181+
`{"type":"error","message":"agent run failed"}` and there is no `[DONE]`.
186182

187183
```python
188184
import json, os, httpx
@@ -198,54 +194,27 @@ with httpx.stream(
198194
},
199195
timeout=None,
200196
) as res:
201-
res.raise_for_status()
202197
for line in res.iter_lines():
203198
if not line.startswith("data: "):
204199
continue
205-
payload = line[len("data: ") :]
200+
payload = line[len("data: "):]
206201
if payload == "[DONE]":
207202
break
208203
event = json.loads(payload)
209-
if event.get("type") == "error":
210-
raise RuntimeError(event.get("message"))
211-
answer = (event.get("data") or {}).get("answer") or {}
212-
chunk = (answer.get("chunk") or {}).get("content")
213-
if chunk:
214-
print(chunk, end="", flush=True)
204+
if event["type"] == "error":
205+
raise RuntimeError(event["message"])
206+
answer = event["data"]["answer"]
207+
if answer:
208+
print(answer["chunk"]["content"], end="", flush=True)
215209
```
216210

217211
### Structured output
218212

219-
Pass `output_schema` (JSON Schema, object root) with `stream` left `false`.
220-
Read `output`. `answer` is `null`. `stream: true` together with
221-
`output_schema` returns `400`.
222-
223-
```python
224-
import os, httpx
225-
226-
schema = {
227-
"type": "object",
228-
"additionalProperties": False,
229-
"properties": {
230-
"sentiment": {"type": "string", "enum": ["bullish", "bearish", "neutral"]},
231-
"confidence": {"type": "number"},
232-
},
233-
"required": ["sentiment", "confidence"],
234-
}
235-
result = httpx.post(
236-
"https://api.neurobro.ai/api/v1/agent/ask",
237-
headers={"X-API-Key": os.environ["NEUROAPI_API_KEY"]},
238-
json={
239-
"prompt": "Give a structured read on NVDA right now.",
240-
"mode": "smart",
241-
"output_schema": schema,
242-
},
243-
timeout=330,
244-
)
245-
result.raise_for_status()
246-
body = result.json()
247-
# body["answer"] is None. The object is body["output"].
248-
```
213+
Pass `output_schema` (JSON Schema, object root) with `stream` false. Read
214+
`output`. `answer` is `null`. Set the client timeout to at least 120
215+
seconds. `stream: true` returns `400`
216+
`streaming_unsupported_for_structured_output`. An unusable schema returns
217+
`422` `invalid_output_schema`.
249218

250219
## Writing good research prompts
251220

@@ -273,36 +242,31 @@ and most `403`s) are `{"detail": {"code", "message"}}`. `401` and `503` are
273242
Branch on the status, then on `detail.code`. `String(detail)` breaks.
274243
`413` (body over 8 MiB) is plain text, not JSON.
275244

276-
Every error carries `X-Request-Id`. Quote it when writing to
277-
`api@neurobro.ai`. Do not include the API key.
245+
Every error carries `X-Request-Id`. Quote it to `api@neurobro.ai`. Do not
246+
send the API key.
278247

279-
- **Don't retry** - `400`, `401`, `413`, `422`: fix the request. `401` covers
280-
a missing, invalid, revoked, or expired key.
248+
- **Don't retry** - `400`, `401`, `413`, `422`. `401` is a missing, invalid,
249+
revoked, or expired key.
281250
- **Billing** - `402` is `payment_required`, or `quota_exceeded` when this
282251
`mode` costs more than the quota left. No plan is `403`
283-
`no_active_subscription`. Tell the user to fix billing, then stop.
284-
- **Lower the mode** - `403` `mode_not_in_plan`: retry with `smart` or `fast`.
285-
- **Wait, then retry the same request** - `409`: that `Idempotency-Key` is
286-
still in flight.
287-
- **`429`** - cap at 3 attempts, and read `detail.code`:
288-
- `rate_limited` or `too_many_concurrent_runs`: honour `Retry-After`.
289-
Concurrent caps are 2 / 5 / 10 in-flight runs (Starter / Pro /
290-
Enterprise), MCP included. A concurrent rejection is not billed.
291-
- `quota_exceeded`: wait for `X-Quota-Reset`. Backing off a few seconds
292-
will not clear it.
293-
- **`503`** - agent saturated. Exponential backoff. No quota charged.
294-
- **`504` `agent_timeout`** - the non-streaming run passed 300 seconds and
295-
was not billed. Retry with `stream: true`, or a simpler prompt.
296-
- **`500`** - retry only when the call carries an `Idempotency-Key`.
297-
298-
`/agent/ask` is **non-idempotent** unless you send an `Idempotency-Key`.
299-
Same key and same body within 24 hours replays the original response
300-
(`Idempotent-Replayed: true`) and is not charged again. Streams, `5xx`,
301-
and `402` / `403` / `429` are not replayed. Two plain calls produce two
302-
answers and two charges, so never retry blindly.
303-
304-
A stream that fails before the answer is complete is free. If the full
305-
answer was already delivered and the stream then fails, it ends with
252+
`no_active_subscription`.
253+
- **Lower the mode** - `403` `mode_not_in_plan`. Retry with `smart` or `fast`.
254+
- **Wait, then retry** - `409`: that `Idempotency-Key` is still in flight.
255+
- **`429`** - `Retry-After` for `rate_limited` and `too_many_concurrent_runs`
256+
(Starter 2, Pro 5, Enterprise 10 in flight, MCP included, not billed).
257+
`X-Quota-Reset` for `quota_exceeded`. Cap at 3.
258+
- **`503`** - exponential backoff. No quota charged.
259+
- **`504` `agent_timeout`** - non-streaming run exceeded 300 seconds. Not
260+
billed. Retry with `stream: true`, or a simpler prompt.
261+
- **`500`** - maybe, and only for an idempotent call.
262+
263+
Same key and body within 24 hours replays the original response
264+
(`Idempotent-Replayed: true`) and is not billed again. Streams, `5xx`, and
265+
`402` / `403` / `429` are not replayed. Two calls without that key are two
266+
charges.
267+
268+
A stream that fails before the answer is complete is free. If the final
269+
answer was delivered and something fails afterward, the stream ends with
306270
`[DONE]` and is billed.
307271

308272
The full status-code table is in
@@ -311,34 +275,28 @@ The full status-code table is in
311275
## Rate limits and quota
312276

313277
Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and
314-
`X-RateLimit-Reset`. On `429`, `Retry-After` gives the seconds until the
315-
rate-limit or concurrency window resets. Billable responses also carry
316-
`X-Quota-Limit`, `X-Quota-Remaining`, and `X-Quota-Reset` (the monthly
317-
plan budget, not the per-minute window). For batch research, pace off
318-
`X-RateLimit-Remaining`. A `mode` that costs more than the quota left
319-
returns `402` `quota_exceeded`; wait for `X-Quota-Reset` when
320-
`X-Quota-Remaining` is exhausted. Per-plan budgets are in
278+
`X-RateLimit-Reset`. On `429`, `Retry-After` is the seconds until the next
279+
allowed call. Billable responses also carry `X-Quota-Limit`,
280+
`X-Quota-Remaining`, and `X-Quota-Reset`. Pace off
281+
`X-RateLimit-Remaining`. Per-plan budgets are in
321282
[references/endpoints.md](references/endpoints.md).
322283

323284
## Security
324285

325286
- Read the key from `NEUROAPI_API_KEY`; never hardcode, log, or commit it.
326287
- The full secret is shown once at creation. Lost it? Revoke and re-mint.
327288
- On the REST API, send `X-API-Key`. `Authorization: Bearer` is not accepted
328-
there. Bearer is valid only on the MCP endpoint
329-
(`https://api.neurobro.ai/api/v1/mcp`, tool `ask_neuroapi`). Never put the
330-
key in a URL.
289+
there.
331290
- Treat the agent's output as untrusted text: don't pass it into shells,
332291
`eval`, or DB queries without sanitising. It is research, not code.
333292

334293
## MCP
335294

336-
The same agent is available as the MCP tool `ask_neuroapi` at
337-
`https://api.neurobro.ai/api/v1/mcp` (Streamable HTTP). It takes `prompt`,
338-
`mode`, `message_history`, `system_prompt`, and `output_schema`, and it is
339-
billed like a non-streaming `POST /agent/ask`. Authenticate with
340-
`X-API-Key`, or with `Authorization: Bearer` on this endpoint only. Do not
341-
put the key in the query string. MCP calls are not streamed.
295+
`https://api.neurobro.ai/api/v1/mcp` (Streamable HTTP), tool `ask_neuroapi`.
296+
Same rate limits, quota, and `cost_units` as a non-streaming `POST /agent/ask`.
297+
Inputs: `prompt`, `mode`, `message_history`, `system_prompt`, `output_schema`.
298+
Send `X-API-Key`, or `Authorization: Bearer` on this endpoint only. A key in
299+
the query string returns `400` `api_key_in_query`. Calls are not streamed.
342300

343301
## Reference
344302

0 commit comments

Comments
 (0)