title: Agent Usage
summary: >-
How to use TerraFin's agent-facing surfaces from Python, CLI, HTTP, and the
hosted assistant widget.
read_when:
- Using TerraFin as an agent tool
- Choosing between stateless and hosted agent surfaces
- Interpreting processing metadata
- Finding the right transport for a workflow
Agent Usage
TerraFin is most useful to agents when it stays on the same path as the product.
That means:
- market and macro responses use the same progressive-history rules as the chart stack
- indicator math matches the chart indicators
- chart-opening uses the same session semantics as the browser UI
- every research response includes
processing
If you are maintaining the runtime itself, read hosted-runtime.md and architecture.md. This document is the usage guide.
If you want to do X, use this tool
Scan this table first before reaching for requests / urllib /
yfinance / pandas-html / regex parsers. Every row below is already shipped
with rate-limit, retry, cache, and progressive-history handling.
| If you want to... | Use this tool |
|---|---|
| Resolve a ticker/name into a TerraFin route | resolve(query) |
| Get a chart-ready OHLC series | market_data(name, depth, view) |
| Get a one-asset snapshot (price action + indicators) | market_snapshot(name, depth, view, force_refresh=False) β response asof is the ISO date of the last bar served; pass force_refresh=True only for time-sensitive snapshots (mid-session, freshly-closed bar) to bypass the 24h yfinance.full cache |
| Get company profile / valuation fields | company_info(ticker) |
| Get earnings history (estimate / reported / surprise) | earnings(ticker) |
| Get income / balance / cashflow statement | financials(ticker, statement, period) |
| List a ticker's recent 10-K / 10-Q / 8-K filings | sec_filings(ticker) |
| Get a single filing's TOC (no full body) | sec_filing_document(ticker, accession, primaryDocument, form) |
| Pull one filing section's markdown body | sec_filing_section(..., sectionSlug, form) |
| Run DCF / reverse DCF / Graham / relative valuation | valuation(ticker, ...) (see SKILL.md for turnaround inputs) |
| Inspect FCF base candidates (3yr_avg / annual / TTM) | fcf_history(ticker, years) |
| Get S&P 500 index-level DCF | sp500_dcf() |
| Get 5y monthly beta vs mapped benchmark | beta_estimate(ticker) |
| Get statistical risk profile (tail risk, drawdown, regime) | risk_profile(name) |
| Run a fundamental quality / moat screen | fundamental_screen(ticker) |
| Get guru portfolio holdings (Buffett / Marks / Druck.) | portfolio(guru) |
| Get FRED-backed economic indicator series | economic(indicators) |
| Get macro summary + chart-ready series | macro_focus(name, depth, view) |
| Scan calendar events for a month | calendar_events(year, month, categories, limit) |
| Detect bubble (super-exp growth + log-periodic osc.) | lppl_analysis(name, depth, view) |
| Find chart-shape-similar historical episodes | similarity_search(ticker, universe, period, top_n) |
| Get market temperature signals | fear_greed(), market_regime(), market_breadth(), trailing_forward_pe() |
| Get top companies by market cap | top_companies() |
| Read the user's watchlist | watchlist() |
| Get chart-matching technical indicators | indicators(name, indicators, depth, view) |
| Get named pattern signals matching the latest bar | patterns(name, depth, view) |
| Read which panel/form the user is currently looking at | current_view_context() (hosted runtime only) |
| Open a chart artifact bound to the session | open_chart(name) (hosted runtime only) |
| List / authenticate / switch hosted models | terrafin-agent models ... (see models.md) |
| Discover capability schemas programmatically | GET /openapi.json β filter paths to /agent/api/* |
Capability signatures with full parameter ranges and worked examples live in
skills/terrafin/SKILL.md.
The route summary further down this page is auto-generated and lists every
HTTP route.
Don't roll your own
Reach for the TerraFin helper before hand-rolling any of the patterns below. Each one has been a real source of breakage (rate-limit, cache miss, parser inconsistency, hidden-API drift).
SEC EDGAR β don't roll your own scrape
If you find yourself reaching for urllib.request.urlopen("https://www.sec.gov/..."),
regex-parsing the accession folder index, or stripping <html> tags by hand β
stop. The same content is one tool call away through the parsed + cached path:
| Manual approach (DON'T) | TerraFin tool (DO) |
|---|---|
urlopen("https://www.sec.gov/Archives/edgar/data/<cik>/<acc>/") to list exhibits |
sec_filing_document(ticker, accession, primaryDocument, form="8-K") β toc carries exhibit-991-press-release / exhibit-992-supplemental-material slugs |
urlopen("https://www.sec.gov/.../q1fy27pr.htm") to grab the earnings PR |
sec_filing_section(..., sectionSlug="exhibit-991-press-release", form="8-K") β returns parsed markdown body |
Strip <p> / <table> / with regex |
already done β sec_filing_section returns clean markdown |
Strip the /ix?doc= viewer wrapper off documentUrl |
use sec_filing_document / sec_filing_section instead of dereferencing the URL yourself |
Why this matters:
- SEC rate-limits aggressively (~10 req/s per IP). The TerraFin helpers
share a single
SECClientwith rate-limit + retry; rawurllibdoes not. - Parsed markdown is cached 30 days under
sec.parsed; raw fetches re-pull every newsletter run. - Bypassing the cache risks SEC IP-banning the host.
The form arg is required for 8-K exhibit content β service defaults to
"10-Q", and 8-Ks called without form="8-K" produce only the 4 KB cover
sheet stub (no exhibits appended). Pull form from
sec_filings(...)["latestByForm"][...]["form"] (or from any flat-list entry)
and pass it through every call.
8-K exhibits β don't bypass fetch_and_parse_filing
If you're tempted to call download_filing(...) then parse_sec_filing(...)
yourself for an 8-K, you'll get the 4 KB cover sheet with no exhibits
appended. The exhibit-appending logic lives only in
fetch_and_parse_filing(cik, accession, doc, "8-K", include_images).
| Manual approach (DON'T) | TerraFin tool (DO) |
|---|---|
parse_sec_filing(download_filing(cik, acc, doc), "8-K") |
fetch_and_parse_filing(cik, acc, doc, "8-K", include_images=False) β appends every EX-99.x exhibit |
Manually loop list_filing_files() β download_exhibit() β parse_sec_filing() |
fetch_and_parse_filing(...) β already does this with per-exhibit error markers |
Call sec_filing_section without form="8-K" |
always pass form="8-K" β service defaults to "10-Q" |
The agent-facing path (sec_filing_section) wraps fetch_and_parse_filing
under the cache; only fall through to fetch_and_parse_filing directly when
writing non-agent data-layer code (route handlers, batch ingestion).
Model catalog β don't reach into _PROVIDER_CATALOG
The provider catalog is a public function, not a private dict.
| Manual approach (DON'T) | TerraFin tool (DO) |
|---|---|
from TerraFin.agent.models.management import _PROVIDER_CATALOG |
from TerraFin.agent.models.management import list_provider_catalog |
_PROVIDER_CATALOG["openai"].featured_model_refs |
get_provider_catalog("openai").featured_model_refs |
| Iterate the private dict to discover providers | for entry in list_provider_catalog(): ... |
The private _PROVIDER_CATALOG mapping may be renamed or reshaped without
notice; list_provider_catalog() / get_provider_catalog(provider_id) are
the stable surface.
Choose a surface
There are two agent-facing HTTP families:
GET/POST /agent/api/*Stateless capability access, best when another agent already owns the model loopGET/POST /agent/api/runtime/*Stateful hosted runtime access, best when TerraFin should own the conversation and tool loop
In the browser, the hosted runtime is exposed through the floating TerraFin Agent
widget available on main interface pages such as /dashboard, /chart, and /stock/<ticker>.
That panel is always the public surface. There is no guru picker in the default product flow.
If the deployment does not have a usable hosted model configured, the widget stays in an info-only state:
- it shows the local setup warning
- it does not create a runtime session
- it does not accept chat input until the hosted model credentials are valid
Hosted runtime chat history is local transcript history:
- each session is stored as an append-only JSONL transcript
- history list and previews are derived from the transcript index
- deleting a session archives the transcript and removes it from active history
- raw tool JSON stays in the transcript for replay, but is hidden from user-facing previews
TerraFin Agent may also route some research questions through hidden investor roles before replying. Today those roles include Warren Buffett, Howard Marks, and Stanley Druckenmiller.
Important product rules:
- users still talk only to
TerraFin Agent TerraFin Agentis the orchestrator; hidden persona roles are reached by its own LLM viaconsult_warren_buffett,consult_howard_marks, andconsult_stanley_druckenmillertool calls (no pre-intercept router β see the architecture diagrams in architecture.md)- the hidden guru path is research-only in v1
- hidden guru sessions are not shown in normal session history
- hidden guru roles cannot be created through the normal public runtime API
- hidden guru session ids are not valid public session/task/approval resources
- internal guru handoff uses a structured memo contract before the main assistant synthesizes a reply
Disclosure
The hosted TerraFin Agent produces research-oriented analysis, not personalized investment advice. A few properties follow from that framing and should be called out to downstream product surfaces, integrators, and end users:
- the agent cannot place trades, hold funds, or take fiduciary responsibility
- outputs are grounded in tool results and what the user says in the same session; the agent should not invent numbers it has not seen in a tool result
- persona consults (Buffett, Marks, Druckenmiller) are framed as research voices, not registered advisor recommendations
- a
confidencescore β₯ 80 returned by a persona consult carries at least one citation β theGuruResearchMemovalidator clamps unsupported high-confidence memos to 60 before returning them to the orchestrator (see guru/memo.py)
The orchestrator's system prompt carries a matching DISCLOSURE paragraph so the
model stays inside this framing. Product surfaces that embed the widget or call
the runtime HTTP API are responsible for any user-facing disclosure copy
their jurisdiction requires β the agent itself does not render one.
Choose a transport
| Transport | Use it when... |
|---|---|
| Python client | TerraFin is importable locally and low latency matters |
| HTTP API | TerraFin is already running as a service |
| CLI | Shell composition is the simplest fit |
| Skill artifact | Another agent environment needs portable instructions |
TerraFinAgentClient(transport="auto") follows the normal rule:
- Python when no
base_urlis set - HTTP when a
base_urlis set
Default request policy
For market and macro requests:
- start with
depth="auto" - inspect the returned
processing - rerun with
depth="full"only when the task genuinely needs long-range context
For company info, earnings, financials, portfolio, and calendar data:
- the payload should already be complete
processing.isCompleteis expected to betrue
Charts are optional. Open them when the chart itself materially helps the task.
Processing metadata
Every structured research response includes a top-level processing object.
{
"processing": {
"requestedDepth": "auto",
"resolvedDepth": "recent",
"loadedStart": "2023-04-04",
"loadedEnd": "2026-04-04",
"isComplete": false,
"hasOlder": true,
"sourceVersion": "yfinance-v2",
"view": "weekly"
}
}
| Field | Meaning |
|---|---|
requestedDepth |
What the caller asked for |
resolvedDepth |
What TerraFin actually returned |
loadedStart / loadedEnd |
Loaded time span for time-series tasks |
isComplete |
Whether older data still exists outside the response |
hasOlder |
Whether the request can be deepened |
sourceVersion |
Provider/cache version hint |
view |
Effective timeframe transform |
Common tasks
Multi-step task recipes. For a one-row "what tool do I need" lookup, scan the tool-index table at the top instead.
Rows marked (helper) are composed module-level functions exported from
from TerraFin.agent import β¦ β not registered capabilities. They wrap
one or more capabilities (e.g. compare_assets calls resolve + market_snapshot
under the hood). They're not in the 30-row capability table because they
don't appear in the agent capability registry.
| Task | Recommended entrypoint |
|---|---|
| Ticker brief | resolve(...) then market_snapshot(...) |
| Market snapshot | market_snapshot(name, depth="auto", view="daily") |
| Compare assets | compare_assets([...], depth="auto", view="daily") (helper) |
| Macro context | macro_context(name, depth="auto", view="daily") (helper) |
| Portfolio context | portfolio_context(guru) (helper) |
| Stock fundamentals | stock_fundamentals(ticker, statement="income", period="annual") (helper) |
| Stock DCF | valuation(ticker, projection_years=..., fcf_base_source=..., breakeven_year=..., breakeven_cash_flow_per_share=..., post_breakeven_growth_pct=...) |
| FCF history candidates | fcf_history(ticker, years=10) |
| SEC filings | sec_filings(ticker) β sec_filing_document(..., form=...) β sec_filing_section(..., sectionSlug=..., form=...). Pass the actual form string ("10-K" / "10-Q" / "8-K" / "8-K/A") on every call β service defaults to "10-Q". For 8-K, the TOC includes exhibit-991-press-release / exhibit-992-supplemental-material slugs holding the earnings PR + CFO commentary bodies. |
| Sentiment / breadth | fear_greed(), market_regime(), market_breadth(), trailing_forward_pe() |
| Calendar scan | calendar_events(year=..., month=..., categories=..., limit=...) |
| Bubble analysis | lppl_analysis(name, depth="auto", view="daily") |
| Chart similarity search | similarity_search(ticker, universe="sp500+nasdaq100+kospi200", period="1y", top_n=20) |
| Open chart | open_chart(...) when the chart is explicitly useful |
See Don't roll your own β SEC EDGAR for the anti-pattern table and why the helper exists. The summary: pass
form="8-K"explicitly (service defaults to"10-Q"), pull it fromsec_filings(...)["latestByForm"][...]["form"].
The full per-capability call signature, parameter ranges, and worked examples (including DCF turnaround mode) live in
skills/terrafin/SKILL.mdβ the skill is the authoritative capability reference for both this doc and external agents.
Minimal examples
Python client
from TerraFin.agent import TerraFinAgentClient
client = TerraFinAgentClient()
snapshot = client.market_snapshot("AAPL", depth="auto", view="daily")
Hosted runtime helper
from TerraFin.agent import create_runtime_session
session = create_runtime_session("terrafin-assistant")
session.send("Compare the S&P 500 and Nasdaq.")
session.display_notebook()
CLI
terrafin-agent snapshot AAPL
terrafin-agent runtime-create-session terrafin-assistant
terrafin-agent models list --all
HTTP
curl "http://127.0.0.1:8001/agent/api/market-snapshot?ticker=AAPL&depth=auto&view=daily"
curl -X POST "http://127.0.0.1:8001/agent/api/runtime/sessions" \
-H "Content-Type: application/json" \
-d '{"agentName":"terrafin-assistant"}'
Browser UI
http://127.0.0.1:8001/dashboard
Use the TerraFin Agent button in the lower-right corner.
Route summary
Stateless capability routes (every hosted-runtime tool also has a parity HTTP
route under /agent/api/* β see skills/terrafin/SKILL.md for the full
30-capability table with Python / CLI signatures).
Data + chart:
GET /agent/api/calendarβ TerraFin calendar events for a month.GET /agent/api/companyβ Company profile and valuation fields for a ticker.GET /agent/api/earningsβ Earnings history (estimate / reported / surprise) for a ticker.GET /agent/api/economicβ Economic indicator series (FRED-backed).GET /agent/api/financialsβ Financial statement table (income / balance / cashflow) for a ticker.GET /agent/api/indicatorsβ Chart-matching technical indicators for one asset.GET /agent/api/lpplβ LPPL bubble analysis (super-exponential growth + log-periodic oscillation detection).GET /agent/api/macro-focusβ Macro summary plus chart-ready series for one instrument.GET /agent/api/market-dataβ Chart-ready OHLC time series for one asset.GET /agent/api/market-snapshotβ Compact market snapshot for one asset.GET /agent/api/portfolioβ Guru portfolio holdings and summary metadata.GET /agent/api/resolveβ Resolve a free-form query into a TerraFin route.
Valuation + fundamentals:
GET /agent/api/beta-estimateβ 5-year monthly beta with adjusted beta, RΒ², benchmark.GET /agent/api/fundamental-screenβ Fundamental quality and moat screen for a ticker.GET /agent/api/risk-profileβ Statistical risk profile (tail risk, convexity, vol regime, drawdown).GET /agent/api/sp500-dcfβ Full S&P 500 DCF valuation (scenarios, sensitivity, methods).GET /agent/api/valuationβ DCF (incl. turnaround mode), reverse DCF, relative valuation, Graham number.
SEC filings:
GET /agent/api/sec-filing-documentβ Filing table-of-contents (sections + char counts) without full body.GET /agent/api/sec-filing-sectionβ Verbatim markdown body of one filing section by slug.GET /agent/api/sec-filingsβ List recent 10-K / 10-Q / 8-K filings for a ticker with EDGAR URLs.
Sentiment / breadth / market state:
GET /agent/api/fear-greedβ CNN Fear & Greed index β score, rating, history.GET /agent/api/market-breadthβ Standalone market-breadth metrics (% advancing, new highs, etc.).GET /agent/api/market-regimeβ Market regime classification with confidence and signals.GET /agent/api/top-companiesβ Top companies by market cap (private API or yfinance fallback).GET /agent/api/trailing-forward-peβ S&P 500 trailing vs forward P/E spread (history + summary).GET /agent/api/watchlistβ The user's current watchlist (read-only).
Other:
GET /agent/api/fcf-historyβ FCF history + 3yr-avg / latest-annual / TTM candidates.GET /agent/api/patternsβ Named market patterns matching the latest bar for one asset.GET /agent/api/similarity-searchβ Chart-pattern similarity search across a stock universe.
View context is read-only. The hosted runtime exposes a
current_view_context()tool that returns the panel and form state the user is currently looking at β including the DCF input form'sprojectionYears/fcfBaseSource/turnaroundModeselections, the FCF history candidates already loaded, and the auto-selected DCF base source. The agent cannot currently write back to the user's frontend form (noapply_dcf_inputs/set_form_statetool exists). If the agent suggests input values, the user applies them manually. This gap is tracked.
Hosted runtime routes:
GET /agent/api/runtime/agentsPOST /agent/api/runtime/sessionsGET /agent/api/runtime/sessionsGET /agent/api/runtime/sessions/{session_id}DELETE /agent/api/runtime/sessions/{session_id}POST /agent/api/runtime/sessions/{session_id}/messagesGET /agent/api/runtime/sessions/{session_id}/approvalsGET /agent/api/runtime/tasks/{task_id}POST /agent/api/runtime/tasks/{task_id}/cancelGET /agent/api/runtime/approvals/{approval_id}POST /agent/api/runtime/approvals/{approval_id}/approvePOST /agent/api/runtime/approvals/{approval_id}/deny
OpenAPI is available at /openapi.json.
Managing hosted models
The hosted runtime now has a small built-in model manager. Use it when you want OpenAI, Gemini, or GitHub Copilot without hand-editing env vars every time.
This command family was inspired by OpenClaw's provider/model UX, but TerraFin implements and persists it through its own runtime and CLI layers. See models.md for the explicit attribution and boundary.
terrafin-agent models list --all
terrafin-agent models current
terrafin-agent models use github-copilot/gpt-4o
terrafin-agent models auth login-github-copilot --set-default
login-github-copilot now runs a full GitHub device-login flow by default. For
non-interactive shells, pass --token instead.
For the full model-management guide, read models.md.