FX forecasting is a bad fit for an LLM used naively — ask a model to predict tomorrow's USD/KES rate and it will produce a plausible-sounding number with no statistical grounding. The useful pattern is different: keep a real time-series or econometric model doing the actual forecasting, and use the LLM agent as the layer that gathers context, reconciles conflicting signals, and turns a number into a decision a treasury team can act on. That division of labour is the whole article.
What the agent is actually for
A forecasting agent earns its keep by doing the things a pure statistical model can't: pulling central bank statements, reading the latest CPI print, checking scheduled rate decisions, and summarizing how those inputs should shift a forecast band that a GARCH or ARIMA model already produced. The model gives you a distribution; the agent explains why this week's distribution is wider than last week's because the Fed meets on Wednesday. Treat the numeric forecast as ground truth generated outside the LLM, and the LLM's job as narrating and adjusting confidence, not inventing the number.
Tool design for FX context gathering
The agent needs a small set of narrow tools rather than one general "search the web" tool: a rates-history lookup against your own time series database, an economic-calendar tool that returns upcoming central bank events and consensus expectations, and a news-retrieval tool scoped to a whitelist of financial sources. Each tool should return structured JSON, not prose — a model reasoning over {"event":"FOMC","date":"2026-07-30","consensus_bps":25} makes fewer arithmetic errors than one parsing a paragraph. Keep the retrieval step separate from the reasoning step: fetch first, then hand the agent a fixed context bundle for that turn, so its output is reproducible against a given snapshot of data.
tools = [{
"name": "get_fx_forecast_band",
"description": "Returns the statistical forecast band for a currency pair over a horizon, produced by the internal ARIMA/GARCH pipeline.",
"input_schema": {
"type": "object",
"properties": {
"pair": {"type": "string", "description": "e.g. USD/KES"},
"horizon_days": {"type": "integer"}
},
"required": ["pair", "horizon_days"]
}
}, {
"name": "get_economic_calendar",
"description": "Returns scheduled macro events (rate decisions, CPI, NFP) in a date window.",
"input_schema": {
"type": "object",
"properties": {
"currencies": {"type": "array", "items": {"type": "string"}},
"start": {"type": "string"}, "end": {"type": "string"}
},
"required": ["currencies", "start", "end"]
}
}]
Structured output for downstream systems
A forecast that a human reads and a forecast that feeds a hedging system are different outputs. Force the model into JSON mode (or Anthropic's tool-use forced-call pattern, or OpenAI's response_format: json_schema) so the commentary and the numeric adjustment are separated: a confidence_adjustment field, a key_drivers array, a recommended_action enum constrained to a fixed set of values your treasury workflow understands. Never let the model free-write a number into a field a downstream system parses with a regex — constrain it with a schema and validate the response before anything touches a hedge ticket.
If the LLM is asked to output a rate prediction directly, it will hallucinate a confident-sounding figure with no traceable derivation. Every numeric forecast in the response should trace back to the statistical model's tool output — the agent's job is to adjust confidence bands and flag risk, not invent price levels.
Human-in-the-loop for treasury decisions
FX exposure decisions move real money, so the agent should stop short of executing anything. A workable pattern: the agent produces a forecast summary and a recommended hedge ratio, that output is logged with the exact context bundle used to generate it, and a treasury analyst approves or overrides before any forward contract or option is booked. Log the rejection reason when an analyst overrides — that feedback is the highest-signal data you have for catching cases where the agent is weighting a stale news item too heavily or missing a domestic-market factor the general economic calendar doesn't cover.
Evaluating forecast commentary quality
You can't eval a forecasting agent the way you'd eval a chatbot. Track two separate things: whether the underlying statistical model's forecast band actually contained the realized rate (a standard backtesting question, nothing to do with the LLM), and separately, whether the agent's narrative correctly identified the dominant driver of that week's move after the fact. The second metric needs a human-graded rubric — did the summary mention the event that actually moved the pair, or did it pad the response with generic macro commentary that would apply to any week. Run that rubric weekly against realized outcomes and you'll catch drift in the agent's source weighting long before it costs anyone money.
Wrapping up
The pattern that holds up: a real forecasting model owns the number, the agent owns the narrative and the context gathering, structured output keeps the two from bleeding into each other, and a human signs off before exposure changes. Skip any of those four and you end up with an LLM quietly making treasury calls it has no statistical basis for.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.