Blog / Product

[01 / 15]

Jun '265 min read

A briefing bot built on a Saturday

An analyst wired his own morning briefing out of the history API, a cron line and about ninety lines of Python. The interesting part isn't the API call. It's the constant on line four.

Emma Barret Product

At 6:34 on a Thursday a Slack channel called #before-open gets three messages from a bot, and the analyst who wrote the bot is asleep for another twenty minutes. Each message is a headline, a ticker, a score and a link. Nothing else. He covers industrials and materials at a two-PM fund, and before he wrote this he was up at six reading down a feed that ran between sixty and a hundred and forty rows depending on the day.

He built it on a Saturday, in roughly ninety lines of Python.

I want to describe it precisely, because "agent" is a word doing an enormous amount of work in this industry right now. What he built has no fleet console and no orchestration page, and it never wanted one. He needed a history endpoint with filters that mean what they say, a key, and somewhere to put the output. The genuinely interesting part of his script isn't any of that. It's the constant on line four.

Ninety lines, and two hops belong to us

His script wakes at 06:30 and asks GET /v1/feeds for everything published since 18:00 the previous evening, with actionability=true and his forty-odd tickers. On his fund's Pro key the lookback window runs 720 hours and a page holds up to 200 items, so an overnight sweep is one request that never comes close to either number. Starter is 48 hours and 50 to a page, which is plenty for a morning sweep and not enough to read backwards through a quarter. Quant goes a year deep, 500 to a page.

The filters are the ones you'd want on a Saturday afternoon with no support channel open. since and until on publication time. symbol, exchange, aggregator. sentiment_min and sentiment_max. Four tag dimensions, corp_activity, market, market_country and economic_category, which OR within a dimension and AND across them, so "US earnings or M&A" is one query rather than three. cursor pages the rest. He uses six of these and ignores the others, which is the correct ratio for a tool you want people to actually pick up.

  1. 1cron, 06:30 localone request
  2. 2GET /v1/feeds?since=…&actionability=true&symbol=…Pro: 720h window, 200 per page
  3. 3local cut at 72his constant, not ours
  4. 4POST to Slack3 items, median morning
Four hops in the Saturday bot. Two of them are ours, and the judgement about what reaches Slack happens in his file.GET /v1/feeds → Slack

Each item comes back with a scoring block, so the sift he does locally is arithmetic on numbers we already sent him rather than a second round trip. That's most of why ninety lines was enough.

At 9:40 he stops writing code and starts asking questions

The other half of his setup is the MCP server, and it does a completely different job. It's an npm package that runs locally over stdio with your own key, so a config block is the whole install:

json
{  "mcpServers": {    "forecite": {      "command": "npx",      "args": ["-y", "@forecite/mcp"],      "env": { "FORECITE_API_KEY": "fc_live_your_key" }    }  }}

That gives the model eight tools. search_feeds takes the same filter axes as the REST call. get_feed pulls one item in full, with the per-symbol analysis and the comments. score_artifact runs the Verdict Engine over text you hand it, which is a Pro feature. list_symbols and get_symbol cover tickers, list_tags returns the dictionary of legal filter values so the model stops guessing at them, list_sources lists the aggregators, and account reports the key's tier and today's usage so the assistant knows when it's spending your quota.

He uses none of it at 6:30. He uses it at 9:40, when something has already happened, a name is halted, and he wants to ask in English what else that ticker has published this quarter and whether any of it scored. That's an interview, with him in the chair. It isn't automation and it doesn't pretend to be.

Filter on the wire when you can

The REST sweep is the right shape for a fixed hour. For anything that has to react during the session, the live feed does the filtering before the data leaves us. You open a WebSocket with your key and send a subscribe frame carrying symbols, exchanges, aggregators, providers, actionability, a sentiment range, and a tags object keyed by dimension. Set snapshot: 10 and you get the last ten matching items replayed before the live stream starts, which is how an agent that reconnects at 13:00 avoids a hole in its own memory. The server acknowledges with the filters it actually applied, so you can log what you asked for against what you got.

Webhooks are the push route for anything that has to keep working when the laptop closes. You register endpoints, each one gets a signing secret, and scored items arrive as POSTs to your own service. Verify the HMAC against the raw body before you parse it, return a 2xx quickly, and do the real work behind a queue. That's the surface for an integration that lives in your infrastructure rather than on your desk.

Warren has a person in front of him

People assume the agent they want is Warren on a timer, and the difference matters more than the feature list.

Warren is the assistant in the sidebar under Chats, available from Starter up. He searches the web, reads a URL you paste, takes a PDF you drag in, and scores a document with the same Verdict Engine that scores the public feed, in-house machine learning fitted against millions of headlines and the price behaviour that actually followed them. He'll give you a direction read even on a document that lands under the gate. He also can't see your feed, deliberately, and he says so rather than guessing.

What he doesn't do is run while you sleep, and that's a boundary rather than an omission. Warren is attended: you hand him something, you watch him work on it, you argue with the answer. Unattended work belongs to your script and your cron line, hitting an API that returns the same scores he'd read. One plan detail people email us about: chat comes with Starter, scoring your own documents doesn't. That's Pro at 100 a day and Quant at 1,000. Free gets 50 realtime items and no scores, which makes it a good way to see the shape of the feed and a poor way to build anything.

His constant is 72

Our actionability gate is 60. It's global, it's published, and it's the same line for a biotech halt and a utility tariff filing.

He tried it, found it too loud for industrials before the open, and set his own cut twelve points higher. He isn't unusual. Nearly every script like this I've been shown has a number near the top of the file that isn't 60, and the number is never round. 72. 68. One at 81, from someone who wanted two items a week and meant it.

That number is the most interesting thing on the desk and it's the one part we don't supply. It encodes what he's already long, how much he trusts his own reading of the sector, and how badly he takes a false positive at 6:34. We publish a gate that says this item is something that happened. He publishes a threshold, to himself, that says this item is worth waking up for. Those are different claims and only one of them can be ours.

I'd like to know what he picks next earnings season, and whether it's still 72 in October.