Skip to main content

Alerts Instead of Dashboards: My AI Agent Stock Bot

case study•10 min read•Updated:

This is a personal side project and a write-up of architecture, not investment advice. The bot never trades. It suggests, and I decide.

Most analytics still works like this: someone builds a dashboard, someone else is supposed to look at it, and the insight arrives when a person happens to have time to interpret a chart. I think that model is on its way out. The next step is not a better dashboard. It is rules that decide, AI agents that check and explain, and a human who approves.

In recent posts I argued that the market now asks AI for proof of effect, that AI should be measured on outcomes, not activity, and that we may need to rethink KPIs and functions altogether. It is easy to say that about other people’s systems. So here is one of mine, taken apart: a small stock bot I built for my own portfolio, and the agents around it.

TL;DR: key takeaways

  • Alerts beat dashboards. I get one short message when something needs a decision, instead of a dashboard I have to remember to open.
  • Rules decide, AI explains. A deterministic rule engine makes the suggestions. Language models explain them and may only make them more cautious, never bolder.
  • Checks before words. Agents run fixed risk and event checks before they write a single sentence.
  • Versioned hand-off. Pipeline and agents communicate through a git branch, so every output is traceable and auditable.
  • Measure the controls. A paper simulation grades the rules over time, and a human decides whether to change them.
  • A human approves. No agent can trade, publish or send anything on its own.

The interesting part is not the stocks. It is the pattern, and it is the same one I would use to take AI from pilot into operation with business data.

The architecture in one picture

Architecture of the stock bot in five layers: read-only sources in five families (portfolio and prices, Nordic news, global news per holding, investor newsletters and podcasts, insider register and earnings calendar) feed a Python rule engine run by a Grok Bot routine around 05:00; it publishes to a git branch called bot-briefs; Grok Bot routines at 05:15, 08:30 and 16:05 read the branch, run risk, event and change checks, and send one short chat message to a human who decides

Five layers, left to right and top to bottom:

  1. Sources, read-only. More than you might think, grouped in five families. Portfolio and prices: positions from my broker through a read-only connection, plus live quotes from Nasdaq’s public API (Finnhub as an optional fallback). Nordic news: RSS from Dagens industri, Breakit and Börskollen, plus a Google News query for Nordic equities. Global and per holding: a Google News search for every holding, SEC EDGAR filings for US names, and a US macro query. Investors and podcasts: the Pareto Investor and Sprezza Substacks, the 25 Minuter podcast feed and about ten investor newsletters read from a dedicated mail label. Events: the Swedish FI insider register and Nasdaq’s earnings calendar. On top of that the model gets a curated reading list (Riksbank, FedWatch, VIX, Börsdata, Placera, Affärsvärlden and others) that it may point to but that is not fetched automatically.
  2. A rule engine on a schedule. A Python package that a Grok Bot routine runs every weekday around 05:00 Stockholm time. It applies plain rules: maximum weight per holding, a stop-loss level against purchase price, caps on how much can sit in one theme, and an adjustment for the market regime.
  3. Published artefacts. The output is not an email. It is a set of files committed to a dedicated git branch: the brief as text, a metadata file with every suggested action, a morning snapshot, and a simulation log.
  4. An agent layer. Scheduled Grok Bot routines pick up those files at 05:15, 08:30 and 16:05, run a chain of check scripts and write a short message.
  5. Delivery and oversight. I get a chat message that says what changed and what, if anything, needs a decision. Nothing else.

Rules decide, models explain

Decision flow: the rule engine suggests buy, hold, reduce or sell; a stop-loss hit locks a sell that no model can change; deterministic risk checks strike buys over theme or weight caps; an optional language-model veto may only downgrade a buy or reduce to hold with at least two cited sources; finally the model explains the result in plain Swedish

The most important design choice was to keep the language model out of the decision. The rule engine produces buy, hold, reduce or sell suggestions, each with the evidence behind it: weight, return against purchase price, which rule fired.

Language models get two narrow jobs. They explain, in plain Swedish, why the rules said what they said. And there is an optional research veto: a model may downgrade a buy or reduce to hold, but only if it cites at least two sources from the news pack with URLs. It can never upgrade anything, and it can never override a stop-loss.

That asymmetry matters. A model that hallucinates can at worst make me do nothing. That is a failure mode I can live with.

Why a git branch as the hand-off point?

The pipeline and the agents never call each other. The pipeline writes to a branch called bot-briefs, and the agents read from it.

This turned out to be one of the better decisions in the project. Every brief an agent read can be traced to a commit. I can diff Tuesday against Wednesday. If a digest looks odd, I can check whether the input was odd or the summary was. And it costs nothing beyond a repository I already had.

It also means the pipeline can move. Over time it has run on my laptop, on Prefect and on GitHub Actions. Today the whole chain, from the rule engine to the last digest, runs as scheduled Grok Bot routines. The branch stayed the same through every move, so the readers never had to change.

Timeline of a weekday in Stockholm time: the rule engine publishes around 05:00, the morning digest runs at 05:15, EIK-Trender sends trends at 07:15, the AI morning brief arrives at 07:50, and short since-this-morning digests run at 08:30 and 16:05

The agent layer: checks before words

When an agent wakes up at 05:15, it does not start writing. It runs four scripts in a fixed order:

  • Risk check. Recomputes weights with live prices and strikes any buy that would push a theme over its cap or a single holding over its maximum weight.
  • Events. Looks up recent insider trades and upcoming earnings dates for the holdings involved. Information only, never a reason to act.
  • Since this morning. At 08:30 and 16:05, compares against the morning snapshot so the message can say what moved, instead of repeating the whole brief.
  • Checks text. Merges everything into a deterministic summary that the agent then turns into a few readable lines.

The rule thresholds live in one file in the repo, imported by both the engine and the checks. Two copies of a rule will drift apart eventually; one copy cannot.

Why alerts instead of dashboards?

The repo still has a small local dashboard. I almost never open it. What I actually use is a message that is short when nothing happened and specific when something did: sell first if a stop-loss is hit, at most one or two optional buys, and a plain “don’t buy” when a theme is already heavy.

That is the same argument I make about AI in companies. A dashboard waits for someone to look at it. An alert with a threshold and a clear owner does the looking for you. The human role moves from finding the signal to deciding what to do about it.

Grading the rules with a paper simulation

Feedback loop: suggest, log the action, confidence, rule and what the checks struck, score the log after 1, 5 and 10 trading days, then report hit rate and what struck buys would have returned, so a human can review and adjust a rule

Every day the engine logs what it suggested, what the checks struck, the confidence and which rules fired. Later runs score that log at fixed horizons: one, five and ten trading days. The digest then reports how often the suggestions pointed the right way, and what the buys the checks struck would have returned.

That last number is the honest one. If a theme cap keeps striking buys that then go up, the cap is costing me money, and the digest says so plainly. The rule is not changed automatically; it is flagged for a human to review. That is the loop I want for any AI system in operation: measure the controls, not just the outputs.

Around the stock bot: a small agent ecosystem

The stock bot is one of several agents that hand work to each other:

  • Ai Omvärld writes a morning brief on AI and technology news.
  • EIK-Trender runs on weekday mornings and sends at most five trends, each with a source, a growth signal and a possible writing angle, into that brief.
  • A website agent reads both, plus the stock digests, and turns what is worth writing about into draft pull requests on this site, like this one.

Agent network: the stock digests, the Ai Omvärld news brief and EIK-Trender feed a website agent that drafts posts as draft pull requests; it asks a human for approval, and only after an explicit yes is anything merged, published or sent to the live site

The hand-offs are asynchronous messages between agents. No agent can publish, send or merge on its own. Anything externally visible waits for my explicit yes.

Cost and oversight

A few choices kept this cheap and calm:

  • No server of my own. Scheduled Grok Bot routines instead of a machine or a paid orchestrator.
  • Expensive models off by default. The scheduled run is deliberately slim: no deep research veto, no email. The veto can be switched on for a manual run when I want it.
  • Secrets only in the environment. Keys live in the agents’ environment, never in the repo. Broker access is read-only.
  • Narrow permissions. The pipeline can write to its own branch and nothing else. The agents can read, check and draft; writing to the outside world needs approval.
  • Small outputs. A message of a dozen lines is cheap to generate and cheap to read.

Why this matters beyond stocks

Replace the portfolio with a business and nothing important changes:

Stock bot Business equivalent
Holdings and prices KPIs, orders, tickets, ERP and CRM data
Stop-loss and weight caps Thresholds, SLAs, budget limits, policy rules
News and newsletters Customer feedback, incidents, market signals
Rule engine suggests Rules flag a deviation and propose an action
Agent checks and explains Agent adds context: what changed, why, what it affects
I decide in a chat message The owner approves in Slack, Teams or the ticket system
Paper simulation Measuring whether the alerts led to better outcomes

This is what I mean by moving AI from pilot to operation. A pilot shows that a model can summarise a report. Operation means the system watches the data all the time, only speaks up when a threshold is crossed, explains itself with sources, and leaves the decision with an accountable person. Governance is not a document on the side; it is built into who may do what: rules decide, models explain, humans approve, and everything is logged.

It also connects to the measurement question. If every alert is logged with what was suggested and what was decided, you can measure effect: time to detection, decisions made, and whether outcomes improved. That is much harder to prove with a dashboard nobody can say they looked at.

What I would tell someone building their own

Start with the rules and the hand-off point, not the model. Decide what the model is not allowed to do before deciding what it should do. Publish intermediate results somewhere versioned. Measure your controls. And send alerts, not dashboards.

None of this is specific to stocks. Swap the broker for an ERP and the newsletters for customer tickets, and you have the shape of most agent systems I would want to run in operation.

Tools Used in This Article

This article mentions several tools from my tech stack.