Install
openclaw skills install drillr-agentAccess Drillr's financial research capabilities — agentic search over company financials, a high-signal market event feed, published analyst articles, and persistent per-user watchlists. Use this whenever the user asks about stock prices, company fundamentals, earnings, SEC filings, market signals, sector trends, or wants to track tickers over time. Requires a user-specific API key obtainable at https://drillr.ai/developer/keys.
openclaw skills install drillr-agentDrillr exposes its AI research agent and financial data pipeline to
external agents through three equivalent channels: MCP (Streamable
HTTP), REST API, and a command-line tool. All three accept the
same drl_* API key and expose the same data.
Your onboarding path depends on ONE question:
Can the user run shell commands on the machine where you are running, and see the output directly in the same conversation?
Physical hardware doesn't matter. A Mac mini, MacBook, home NAS, Raspberry Pi, or cloud VM can all serve either path. What matters is whether the user's current channel to you is co-located with your shell or relayed through a chat channel.
Signals that suggest Path A:
ls ~/.config/ back to you→ Use Onboarding A below.
Signals that suggest Path B:
export or config-edit
commands and run them immediately→ Use Onboarding B below.
Quick setup question: are you talking to me through a terminal on the same machine I'm running on — where I can suggest shell commands for you to run — or through a separate channel like Telegram / WhatsApp / a web chat?
Do NOT attempt any tool call until you have a drl_* key accessible to
your runtime. If it's missing, run the onboarding path that matches
your deployment context.
The user reaches you through a text-only relay and cannot touch your filesystem. They will complete the key creation from whatever browser they have (phone, tablet, or desktop) and paste the key back to you.
Step 1 — Tell the user (verbatim):
To use Drillr I need an API key. From any browser (your phone is fine):
- Open https://drillr.ai/developer/keys
- Sign in — Google sign-in is the quickest; email/password also works
- Tap "Create API key" → give it a name (e.g. "my-agent") → copy the
drl_...string- Paste it back to me here. The key is shown only once.
After I confirm it works, you can delete your message.
Step 2 — When the key arrives, persist it:
Write it to ~/.config/drillr/config.json with file mode 0600:
{ "api_key": "drl_..." }
Equivalent shell:
mkdir -p ~/.config/drillr
umask 077
cat > ~/.config/drillr/config.json <<EOF
{ "api_key": "$KEY" }
EOF
chmod 600 ~/.config/drillr/config.json
Step 3 — Verify the key works:
curl -sS -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer drl_..." \
https://gateway.drillr.ai/api/v1/watchlists
Expect HTTP 200. On 401, the key is invalid — apologize, ask the
user to regenerate, and rerun Step 1.
Step 4 — Confirm to the user, masked:
Stored
drl_xxxxxxxx_...e9f2. You can safely delete your message now.
Rules:
~/.config/drillr/config.jsonThe user can run shell commands and see their output. Pick ONE of the
three equivalent options and instruct the user accordingly. All three
expect the same drl_* key created at
https://drillr.ai/developer/keys.
B1. MCP via Claude Code (recommended for Claude Code users)
Tell the user:
Create an API key at https://drillr.ai/developer/keys (Google sign-in is easiest)
Add to
~/.claude.json(or merge into the existingmcpServersobject):{ "mcpServers": { "drillr": { "type": "http", "url": "https://gateway.drillr.ai/mcp", "headers": { "Authorization": "Bearer ${DRILLR_API_KEY}" } } } }Add
export DRILLR_API_KEY=drl_...to your shell rc (~/.zshrc/~/.bashrc) and restart the shellRestart Claude Code.
/mcpshould listdrillras connected.
B2. CLI
npm install -g drillr-cli
drillr auth set-key drl_...
drillr watchlist list # verify: should list (or print "no watchlists yet")
B3. REST with env var
export DRILLR_API_KEY=drl_...
curl -H "Authorization: Bearer $DRILLR_API_KEY" \
https://gateway.drillr.ai/api/v1/watchlists
Pick based on your runtime's capabilities:
| Runtime characteristic | Preferred channel |
|---|---|
| Has native MCP client support | MCP |
| HTTP only (no MCP, no shell) | REST |
| Shell / subprocess available | CLI or REST |
All three are equivalent in data and rate limit. MCP tool names operate by natural names (e.g. watchlist by name); REST uses UUIDs.
searchAsk natural-language questions about companies, tickers, sectors, filings, earnings. Runs 5-15s server-side and returns markdown text with source references.
| Channel | Call |
|---|---|
| MCP | search({ question, session_id?, context? }) |
| REST | POST /api/v1/search with { question, session_id?, stream? } |
| CLI | drillr search "<question>" |
Session continuity: pass the returned session_id in the next
call to continue the same research conversation. Use context to
pass background info that refines the answer.
Data coverage:
When to use search:
Example questions that work well:
signalsA curated investment-event feed. Each signal is one market event (one SUBJECT × one ACTION × one TIME), already aggregated across outlets — you get one record per event, not one per article.
Coverage — sources rolled into the feed:
Freshness: signals appear within ~3–5 minutes of the originating event.
| Channel | Call |
|---|---|
| MCP | signals({ tickers?, sector?, since?, limit?, offset? }) |
| REST | GET /api/v1/signals?tickers=AAPL,MSFT§or=Technology&since=...&limit=20 |
| CLI | drillr signals --tickers AAPL,MSFT --limit 5 |
Response shape: { headline, summary, suggested_tickers[], sector[], created_at }, ordered newest first.
article_list / article_getResearch articles spanning company-specific analysis, event coverage, and industry trackers.
What you'll find:
| Channel | Call |
|---|---|
| MCP | article_list({ ticker?, tag?, limit?, offset? }) / article_get({ article_id }) |
| REST | GET /api/v1/articles?ticker=NVDA&limit=10 / GET /api/v1/articles/:id |
| CLI | drillr articles list --ticker NVDA / drillr articles get <uuid> |
article_get returns the article body (markdown), plus topics and
references arrays. article_list returns 11 public fields per row
(id, title, summary, content, related_tickers, tags, sector, citation,
published_at, created_at, word_count).
Per-user ticker collections. Owner-isolated (RLS): each key only sees
and mutates its owner's watchlists. Attempting to access another user's
watchlist by UUID returns 404, not 403.
| MCP (by name) | REST (by UUID) |
|---|---|
watchlist_list | GET /api/v1/watchlists |
watchlist_create({ name, tickers? }) | POST /api/v1/watchlists |
watchlist_add({ ticker, watchlist_name? }) | POST /api/v1/watchlists/:id/tickers |
watchlist_remove({ ticker, watchlist_name? }) | DELETE /api/v1/watchlists/:id/tickers/:ticker |
watchlist_delete({ watchlist_name }) | DELETE /api/v1/watchlists/:id |
CLI: drillr watchlist {list|create|add|remove|delete} — see
drillr watchlist --help.
MCP tools accept watchlist names (chat-friendly). REST uses UUIDs (URL-friendly). If
watchlist_nameis omitted on add, a default "My Watchlist" is used (created on miss).
User: "Can you do a daily morning briefing on my portfolio?"
watchlist_list — see what tickers the user already trackswatchlist_createsignals({ tickers: [...watchlist_tickers], since: "<24h-ago ISO>" })search({ question: "Deeper context on <headline>" })article_list({ ticker: ... }) for any ticker with fresh activityUser: "What's Nvidia's market cap?"
search({ question: "What is NVDA's current market cap?" })User: "Any interesting biotech moves this week?"
signals({ sector: ["Health Care"], since: "<7d-ago ISO>", limit: 30 })article_list({ ticker }) or
a follow-up search with session_id from the prior call| HTTP | code string | What to do |
|---|---|---|
| 400 | invalid_body / invalid_query / invalid_id | Fix parameter shape and retry (don't pester the user) |
| 401 | unauthenticated / key_invalid | Re-read the stored key; if still 401, rerun Prerequisites — the key is absent or wrong |
| 401 | key_revoked | Tell the user their key was revoked; they need to create a new one at the developer portal |
| 401 | key_expired | Tell the user their key expired; same fix |
| 403 | Key is valid but lacks external scope — user needs to issue a different key | |
| 404 | not_found | Resource doesn't exist, or RLS hides it (someone else's). Do NOT assume just-deleted |
| 429 | Inspect retry_after_seconds in the body; sleep and retry | |
| 502 | upstream_error | Transient data-source failure; retry once after 2-3s, then surface to user |
On any 401: re-read ~/.config/drillr/config.json or the
DRILLR_API_KEY env var BEFORE asking the user. You have the
configuration — diagnose first, then instruct.
Never tell the user to "check their configuration."
30 requests per minute per API key. On 429 the response body
includes retry_after_seconds (1-60s). For workflows that fan out
(e.g., scanning a 50-ticker watchlist), pace at ≤0.5 req/s or batch
via a single search or signals call with multiple tickers.
Drillr also supports OAuth 2.1 for MCP clients that implement Dynamic Client Registration (e.g., Claude Code's built-in MCP OAuth). This skill deliberately does not cover that path because:
For agent automation, prefer the drl_* API key flow above. If you
are a human user setting up Claude Code on your own laptop and prefer
the OAuth UX, see the Drillr developer portal
(https://drillr.ai/developer/docs).
https://gateway.drillr.aihttps://gateway.drillr.ai/mcpdrillr-cli (npm install -g drillr-cli)Tracks External API v1 (2026-04). Breaking changes will ship as
/api/v2/* alongside /api/v1/*.