TerraFin / docs /agent /usage.md
sk851's picture
docs(agent): refactor for discoverability + fix post-split stale paths
3020135
metadata
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> / &nbsp; 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 SECClient with rate-limit + retry; raw urllib does 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 loop
  • GET/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 Agent is the orchestrator; hidden persona roles are reached by its own LLM via consult_warren_buffett, consult_howard_marks, and consult_stanley_druckenmiller tool 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 confidence score β‰₯ 80 returned by a persona consult carries at least one citation β€” the GuruResearchMemo validator 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:

  1. Python when no base_url is set
  2. HTTP when a base_url is 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.isComplete is expected to be true

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 from sec_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's projectionYears / fcfBaseSource / turnaroundMode selections, 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 (no apply_dcf_inputs / set_form_state tool exists). If the agent suggests input values, the user applies them manually. This gap is tracked.

Hosted runtime routes:

  • GET /agent/api/runtime/agents
  • POST /agent/api/runtime/sessions
  • GET /agent/api/runtime/sessions
  • GET /agent/api/runtime/sessions/{session_id}
  • DELETE /agent/api/runtime/sessions/{session_id}
  • POST /agent/api/runtime/sessions/{session_id}/messages
  • GET /agent/api/runtime/sessions/{session_id}/approvals
  • GET /agent/api/runtime/tasks/{task_id}
  • POST /agent/api/runtime/tasks/{task_id}/cancel
  • GET /agent/api/runtime/approvals/{approval_id}
  • POST /agent/api/runtime/approvals/{approval_id}/approve
  • POST /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.

Read next