Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
LLM_MODELNoModel ID (default: deepseek-chat)deepseek-chat
INVEST_HOMEYesPath to the data directory (e.g., ~/openInvest)
LLM_API_KEYYesAPI key for the LLM provider (required for automated decisions)
LLM_BASE_URLNoBase URL for the LLM API (default: https://api.deepseek.com)https://api.deepseek.com

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
statusA

Get a full snapshot of the user's portfolio: cash balances per currency, every holding with units / average cost / live price, and unrealized P&L per position and in total.

Use when the user asks "show my portfolio", "how is my P&L", or before proposing any trade. Read-only; fetches live quotes, so values change between calls.

Returns: Object with cash (currency → amount), all_holdings (every position, priced the same way whatever the symbol: units, avg_cost, live price, market value, pnl_pct; null price fields when a quote is unavailable; each carries alerts, the user's per-asset alert lines with the distance still to go, e.g. "距 price_below 还有 3.2%" — a tracked asset with alert lines but no holding row appears as an is_tracking_only row), total_assets_cny, fx (rate to CNY per non-CNY currency in use), an optional gold summary when a gold-per-gram holding exists, and performance (real-account TWR 30d / YTD / since inception, XIRR, max drawdown with peak/trough dates, annualised volatility, return vs the configured benchmark, price_basis per symbol (raw | adjusted), and data_quality; or {"status": "insufficient_history"} until the ledger spans 2 trading days), income_30d (dividends / interest received in the last 30 days by currency; only present when there are any), and pending_fund_orders + pending_fund_orders_line (off-exchange fund orders placed but not yet confirmed — cash already deducted, total_assets_cny counts them at face value; only present when there are any).

doctorA

Health check, the first call of a session (same output as run.sh doctor, for agents without shell access): is onboarding done, and which optional pieces are missing.

status is "ready" when memory (user / strategy / portfolio) is initialized, or "needs_setup" when it is not (or portfolio.md is still the v1 format) — only then hand over to the invest-setup skill. A missing LLM key or mail credentials never makes it "needs_setup": those checks entries are marked optional_for_coordinator / optional_for_email. The Coordinator path (prepare_committee + subagents) works without a key; only the Direct path (run_committee, cron) needs one, see direct_ready.

Read-only; makes one short HTTP probe to the configured LLM endpoint when a key is set.

Returns: Object with status, version, coordinator_ready, direct_ready, next_step, and checks (name / status / detail / hint per check).

strategyA

Get the user's investment strategy: target stock/cash allocation, the list of tracked assets (per-asset investment cap, purchase channel, fee settings), and long-term insights distilled by the nightly Dreaming memory-consolidation job.

Use when deciding whether a proposed trade fits the user's plan, or when the user asks "what is my strategy / what am I tracking". Read-only.

Returns: Object with target_allocation (stock/cash ratios), target_assets (tracked symbols with constraints), and insights (distilled lessons from past decisions).

historyA

Get the most recent trade records and committee verdict history.

Use when the user asks "what did I buy recently" or "what did the committee decide lately". Read-only.

Args: n: Maximum number of recent trades to return (default 10).

Returns: Object with trades (each with symbol, direction, units, price, timestamp, status) and recent committee verdict records.

live_pricesA

Fetch a one-shot market backdrop: spot gold (USD/oz and CNY/gram), USDCNY and AUDCNY FX rates, the NDQ.AX ETF price, the VIX volatility index, and the 10-year US Treasury yield (TNX). A fixed set of reference instruments, independent of what the user holds (use status for the user's own positions).

Use for quick market context before analysis or when the user asks "how is the market / what's the gold price". Read-only; single batch, no arguments.

Returns: Object keyed by instrument (GC_F_usd_per_oz, gold_cny_per_gram_spot, USDCNY, AUDCNY, NDQ_AX, VIX, TNX) plus as_of ISO timestamp. A field is null when its upstream quote is unavailable.

what_ifA

Simulate portfolio P&L for a hypothetical price move: "what happens to my portfolio if moves ±pct% / reaches ". Pure arithmetic over current holdings — no LLM call, instant, free.

Use when the user asks scenario questions like "if the Nasdaq drops 10%, how much do I lose". Provide exactly one of pct or price.

Args: symbol: yfinance ticker held or tracked by the user (e.g. "NDQ.AX", "GC=F", "510300.SS"). pct: Hypothetical percent change, e.g. -10 for a 10% drop. price: Hypothetical absolute target price (alternative to pct).

Returns: Object with the position's simulated value change and the resulting portfolio-level P&L delta.

rebalance_planA

Compute a rebalance list against the target allocation in strategy.md: what to BUY / SELL, how much, in whole lots, and why. Only produces the list, places no order — the human executes. No LLM call.

Use when the user asks "do I need to rebalance", "how far am I from my target allocation" or "what should I buy/sell to get back on target". Per-asset targets come from target_assets[].target_pct in strategy.md; assets without one split target_allocation_stock equally (target_source: "equal_split"). Lot sizes: A-shares 100, convertible bonds 10, off-exchange funds by amount, HK/others 1 (HK lot size is unknown — see lot_note).

Args: mode: "cash_only" | "sell_to_rebalance" | "hybrid" (default). band_pct: Drift band in percentage points, default 5.

Returns: rows (per target asset: current_pct / target_pct / drift_pct / action BUY|SELL|NONE / amount in base currency / units / reason), totals (cash_after, turnover, n_trades), unmanaged holdings, warnings; or {"status": "error", "error": ...}.

disciplineA

Get the committee's discipline ledger: how often it chose inaction (HOLD ratio), how many impulsive user trades its rules intercepted, and the counterfactual money saved/lost by those interventions (ADR-023: the system's proven value is discipline and transparency, not alpha).

Use when the user asks "what has the committee blocked" or "is this tool actually helping". Read-only.

Returns: Object with summary (structured stats) and markdown (the same ledger pre-rendered for direct display to the user).

decisionsA

Get the unified decision ledger: every committee verdict joined with rule interventions, the user's actual executions or refusals (with reasons), and post-hoc outcome data — plus an adoption-rate summary.

Answers "how often did I follow the advice", "which recommendations did I skip", and "what did the safety rules rewrite". Read-only. Filter by symbol / verdict to answer questions about one asset or one kind of call; the list is capped at limit (newest first) so a year of history doesn't flood the context — count and summary still cover every match.

Args: days: Look-back window in days (default 90). symbol: Only decisions on this ticker (case-insensitive). verdict: Only decisions with this verdict. limit: Max decisions listed (default 20; 0 = all).

Returns: Object with count (all matches), returned (listed), summary (adoption rate and aggregates over all matches), and decisions (newest first; each entry has decision_id, verdict, confidence, intervention, executed flag, matched trades, and outcome).

explain_decisionA

Get the full reasoning behind one committee verdict: the complete 4-role debate transcript with the CIO memo, plus the path-probability snapshot the CIO saw at decision time.

Use when the user asks "why was today's verdict HOLD" or wants to audit a past decision. Read-only.

Args: decision_id: "/", e.g. "2026-07-03/GC=F" — exactly as returned in the decisions tool output.

Returns: Object with verdict, confidence (the CIO's self-reported number, kept for the record), confidence_lookup (show this to the user instead: how similar verdicts (live + paper fleet) turned out 30 days later), alloc_cny, transcript_markdown (render this to the user), and path_snapshot (may be null).

record_executionA

Record whether the user executed or declined a committee verdict, with their reason. Appends to the execution ledger; idempotent — replaying the same record is a no-op, so retries are safe.

Call when the user says "I bought it / I didn't buy / I disagree". When they decline, ask one short question for the reason first — this closes the adoption-rate loop that decisions reports on.

Args: decision_id: "/" from the decisions output. executed: True if the user acted on the verdict, False if declined. reason: The user's stated reason (especially when declined). trade_ids: Optional trade record IDs to link explicitly.

Returns: The stored execution record, or {"status": "error", "error": ...}.

ingest_eventA

Feed a finance news item you (the host agent) found into the event ledger, graded and mapped to affected symbols, stored for committee RAG recall.

Preferred: normalize it yourself — pass one_line_claim, stance, severity (and ideally affected_symbols). The backend then only validates and stores it; no backend model is involved. Without those fields the backend model normalizes it, which fails when the backend runs keyless (agent mode) — you get an error telling you which fields to add.

You have far better search reach than the self-hosted crawler (including Chinese-language sources) — proactively feed news relevant to the user's holdings, especially A-share/regional coverage the crawler misses. Idempotent: re-sending the same url or claim does not double-insert. Requires a backend LLM key.

Args: title: Headline of the news item. url: Canonical source URL (also the dedup key). snippet: Short excerpt or summary of the article body. source: Publisher name (e.g. "Reuters") — the news outlet. published_at: ISO 8601 publication time, if known. ingested_by: Your own agent identity (e.g. "hermes") for provenance; distinct in meaning from source.

Returns: Ingestion result with the normalized event id(s), dedup status, and committee_task_id — set when a new holding-relevant event (severity ≥ mid, non-neutral) triggered a rate-limited committee re-run. In agent mode it is "queued:": the re-run waits for you in pending_committees. This tool is disabled in advisory mode.

pending_newsA

News the backend fetched but did not normalize because reasoning is delegated to you (agent mode). For each relevant item call ingest_event with one_line_claim / stance / severity / affected_symbols; pass the irrelevant ones back here as dismiss_urls. Items leave the queue once ingested or dismissed, and expire after 48h.

daily_reportA

Assemble today's daily report (portfolio, verdicts, performance, holdings digest) and return it as full_report Markdown for you to deliver.

Agent mode (keyless backend): run prepare_committee → roles → submit_committee for every target asset FIRST; this tool then only reads today's submitted verdicts — nothing is re-run by a backend model. Assets without a submitted verdict are listed in missing_verdicts: treat any entry there as a failure and report it. Backend mode: runs the backend committee itself (needs a backend LLM key, takes minutes).

pending_committeesA

Committee re-runs that events or price moves requested while reasoning is delegated to you (agent mode). For each item run prepare_committee, the roles, then submit_committee; an item is done once a newer verdict for that symbol is submitted. Requests expire after 24h.

news_sourcesA

List the news feed sources the crawler pulls from: the built-in default feeds plus user-added extra feeds. Extra feeds can be added/removed with add_news_source / remove_news_source; defaults are fixed.

Use when someone asks "what news sources do you follow" or before adding/removing a source.

add_news_sourceA

Add an RSS/Atom feed to the crawler's source list. The URL must be http(s) on a public host (fetched directly, not via HTTP(S)_PROXY), and is live-probed before saving — a URL that doesn't parse as a feed is rejected. Idempotent: re-adding an existing URL returns the existing entry. Capped so the list can't grow unbounded.

Use when someone says "follow 's news" / "加个新闻源".

remove_news_sourceA

Remove a user-added news feed by name or URL. Built-in default feeds cannot be removed.

buyA

Record a buy in the local ledger: adds to an existing position with weighted-average cost, or opens a new position for an unseen symbol. This bookkeeps a trade the user already placed with their broker — openInvest never places real orders.

Confirm symbol, units, and price with the user before calling; this moves ledger cash. A position the user already held before using openInvest is not a purchase: record it with record_existing_position. Off-exchange China mutual funds (FUND:<6 digits>) settle T+1 or later at the NAV of the pricing day: use place_fund_order + confirm_fund_order instead (buy books them as instantly filled and total assets dip by the amount until the real confirmation).

Args: symbol: yfinance ticker (e.g. "AAPL", "510300.SS"). Gold = "GC=F", booked in CNY per gram only (units = grams, currency "CNY", kind "metal", unit_label "克"). units: Quantity bought; must be > 0. price: Execution price per unit, in currency. currency: Currency of price; omitted = the existing position's currency (CNY if new). kind: Asset kind tag: "equity", "etf", "metal" (gold), "crypto", "bond", "fund", "other". unit_label: Human display label for units (default "股", i.e. shares). idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Updated position summary, or {"status": "error", "error": ...}.

record_existing_positionA

Record a position the user already held before using openInvest (onboarding backfill) WITHOUT touching ledger cash. History is marked funding_source: external_funding, source: mcp:existing_position.

Only for positions that status does not list yet — calling it for a symbol already there adds the units again (double count). A new purchase paid from ledger cash is buy. Does not add the symbol to the tracked list; use track_asset for committee coverage.

Args: symbol: yfinance ticker (e.g. "AAPL", "510300.SS"). Gold = "GC=F", booked in CNY per gram only (units = grams, currency "CNY", kind "metal", unit_label "克"). units: Quantity held; must be > 0. price: Average cost per unit, in currency. currency: Currency of price; omitted = the existing position's currency (CNY if new). kind: Asset kind tag: "equity", "etf", "metal" (gold), "crypto", "bond", "fund", "other". unit_label: Human display label for units (default "股", i.e. shares). idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Updated position summary, or {"status": "error", "error": ...}.

sellA

Record a sell in the local ledger: reduces the position's units (average cost unchanged) and credits cash in the holding's cost currency. Bookkeeps a trade already executed at the user's broker — openInvest never places real orders.

Confirm symbol, units, and price with the user before calling; this moves ledger cash.

Args: symbol: yfinance ticker of an existing holding. units: Quantity sold; must be > 0. price: Execution price per unit, in the holding's cost currency. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Updated position summary, or {"status": "error", "error": ...}.

depositA

Record a cash deposit into the ledger, in any currency. Bookkeeping only — no real payment system is connected.

Args: currency: ISO-style currency code, e.g. "CNY", "USD", "AUD". amount: Amount to add; must be > 0. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Updated cash balances, or {"status": "error", "error": ...}.

withdrawA

Record a cash withdrawal from the ledger, in any currency. Fails if the balance is insufficient. Bookkeeping only — no real payment system is connected.

Args: currency: ISO-style currency code, e.g. "CNY", "USD", "AUD". amount: Amount to remove; must be > 0. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Updated cash balances, or {"status": "error", "error": ...}.

record_dividendA

Record a dividend (or interest) the user already received: credits ledger cash by amount - tax_withheld, positions unchanged. It counts as account return (inside NAV), not as a deposit. Bookkeeping only — openInvest never moves money.

Confirm symbol, gross amount, withholding tax, and the date with the user before calling; this moves ledger cash. A symbol that is neither held nor in the ledger is rejected (typo guard).

Args: amount: Gross amount before withholding tax; must be > 0. currency: Currency of the cash credited. symbol: Ticker (required for dividends; optional for interest). kind: "dividend" (default) or "interest". tax_withheld: Tax withheld at source; credited cash = amount - tax_withheld. reinvest: DRIP — buy more symbol with the net amount. reinvest_price: Price per unit for the reinvestment (default: stored raw close). trade_date: YYYY-MM-DD the cash arrived (default today). note: Free-text note. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Cash credited and new balance, or {"status": "error", "error": ...}.

record_feeA

Record a fee or a tax the user already paid: debits ledger cash, positions unchanged. It is an account cost (inside NAV), not a withdrawal. Trade commissions need no separate entry — buy / sell already book the trade. Fails if the currency's cash balance is lower than the amount.

Confirm the amount and date with the user before calling; this moves ledger cash.

Args: amount: Amount paid; must be > 0. currency: Currency of the cash debited. kind: "fee" (default) or "tax". symbol: Related ticker (optional). trade_date: YYYY-MM-DD it was charged (default today). note: Free-text note. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: Cash debited and new balance, or {"status": "error", "error": ...}.

record_splitA

Record a stock split / reverse split: units x ratio, average cost / ratio, cash unchanged (market value is unchanged). Call it once per split — a second call multiplies the position again; use an idempotency_key if unsure whether an earlier attempt landed. Rejected when the ledger already has trades / corrections for the symbol on or after trade_date (their units are already post-split, so multiplying the whole snapshot would invent shares) — pass ledger_only=true if the snapshot is already correct.

Confirm symbol, ratio, and ex-date with the user before calling; this rewrites the position's units and average cost.

Args: symbol: Ticker that split. ratio: New / old shares (10-for-1 = 10; 1-for-10 reverse = 0.1). trade_date: Ex-date YYYY-MM-DD (default today). note: Free-text note. ledger_only: Write the ledger row only; do not change units / average cost. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: New units / average cost (plus a follow_up hint), or {"status": "error", "error": ...}.

record_return_of_capitalA

Record a return of capital (some ETF / REIT distributions): credits ledger cash, lowers the holding's average cost by amount / units (a cost reduction, not income), units unchanged. Cost floors at 0; any excess is reported as excess_over_cost (treat as a capital gain).

Confirm symbol, amount, and date with the user before calling; this moves ledger cash and changes average cost.

Args: symbol: Held ticker. amount: Cash received; must be > 0. currency: Currency of the cash (must match the holding's cost currency). trade_date: YYYY-MM-DD received (default today). note: Free-text note. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: New average cost, or {"status": "error", "error": ...}.

place_fund_orderA

Record the first leg of an off-exchange fund purchase the user already placed with the fund platform: cash - amount, and the order is tracked as in transit (status.pending_fund_orders). Total assets do not change (the in-transit amount counts at face value), so there is no fake dip between order day and confirmation. Shares arrive when the pricing-day NAV is published: the fund_confirm job confirms automatically, or call confirm_fund_order. Bookkeeping only — openInvest never places orders.

The expected confirm date uses a Monday-Friday calendar (no China holiday table) and a lag by fund type (QDII / FOF are slower, read from the fund's profile); the result says so (calendar, lag_source).

Confirm fund, amount, and order time with the user before calling; this moves ledger cash.

Args: symbol: FUND:<6 digits>. amount: Subscription amount in CNY; must be > 0. currency: Currency of the amount (CNY). order_ts: Order time, ISO 8601 Beijing time (default now). note: Free-text note. idempotency_key: Reuse the same key when retrying this exact call; recorded once.

Returns: order_id, pricing day (nav_date), expected confirm date, and new cash balance, or {"status": "error", "error": ...}.

confirm_fund_orderA

Second leg of an off-exchange fund purchase: turn an in-transit order into shares at the pricing day's NAV (units = (amount - fee) / nav; average cost updates, cash unchanged). The fund_confirm job does this automatically every weekday evening, so call it manually only to supply a NAV / fee yourself or to confirm early.

Safe to call twice: an order that is already confirmed returns {"status": "already_confirmed"} (a cancelled one {"status": "cancelled"}) and nothing changes. If the pricing-day NAV is not published yet the result is {"status": "pending_nav"} and the order stays in transit.

Args: order_id: The order to confirm. nav: Unit NAV; omit to use the published NAV of the pricing day. fee: Subscription fee in CNY (default 0).

Returns: Units added, NAV used and new average cost, or {"status": "error", "error": ...}.

cancel_fund_orderA

Cancel an in-transit off-exchange fund order that was never executed (the user withdrew it on the fund platform): the amount returns to ledger cash. Only orders still in transit can be cancelled — a confirmed order already holds shares (use sell to book a redemption).

Confirm with the user before calling; this moves ledger cash.

Args: order_id: The in-transit order to cancel.

Returns: Cash returned and new balance, or {"status": "error", "error": ...}.

set_allocationsA

Update the strategy's target allocation: the stock/cash ratio and/or the per-asset target weights that rebalance_plan reads, and/or the per-asset alert lines the price sentinel watches. The stock and cash values must sum to ≈1.0, and the per-asset weights must sum to at most the stock target; schema validation rejects and rolls back any write that would corrupt the strategy file. Everything in one call is validated and written atomically — to lower the stock target below the current sum of per-asset weights, pass the new weights in the same call.

Use when the user says e.g. "set my target to 70% stock / 30% cash" or "put 30% in 510300.SS and 20% in gold".

Args: target_allocation_stock: Stock weight in [0, 1], e.g. 0.7 (with cash). target_allocation_cash: Cash weight in [0, 1], e.g. 0.3 (with stock). target_pcts: {symbol: weight in [0, 1]} per tracked asset; null clears. alerts: {symbol: {rule: value}} alert lines per tracked asset; null clears a rule (or, for a whole symbol, all its rules).

Returns: The updated allocation and target assets, or {"status": "error", "error": ...}.

track_assetA

Add a symbol to the tracked-asset list, or update an existing entry (idempotent upsert: only the fields you pass are changed). The tracked list decides which symbols the committee and DCA jobs cover. The alert_* parameters set per-asset alert lines the price sentinel checks every few minutes (price lines: 24h cooldown; day-move lines: once per trading day); each one you pass overwrites that line only. To clear a line use set_allocations with a null value. Delivery needs INVEST_EVENT_ALERT=1 on the server (default off — without it a hit is only logged to the event store, nothing is sent).

Use when the user says "track AAPL", wants to change a tracked asset's cap/channel/fees/target weight, or says "alert me when X drops below N" / "tell me if it falls 3% in a day".

Args: symbol: yfinance ticker to track (e.g. "AAPL", "0700.HK", "BTC-USD"). max_single_invest_cny: Per-decision investment cap in CNY. On a new entry it defaults to the strategy-level max_single_invest_cny; optional on update. display_name: Human-friendly name shown in reports. channel: Where the user actually buys it (broker/app name). price_offset_pct: Systematic offset between the quote and the user's actual fill price, in percent (e.g. bank gold spread). sell_fee_pct: Sell-side fee in percent, used by fee-aware math. target_pct: Target weight as a fraction of total assets in [0, 1] (read by rebalance_plan); all tracked assets' weights must sum to <= target_allocation_stock or the write is rejected. alert_price_above / alert_price_below: price lines (status.current_price basis). alert_day_drop_pct / alert_day_rise_pct: the latest daily bar's move vs the previous close, percentage points. alert_drawdown_from_cost_pct: held position below average cost, percentage points.

Returns: The stored asset entry, or {"status": "error", "error": ...}.

untrack_assetA

Remove a symbol from the tracked-asset list — the committee and DCA jobs stop covering it. Holdings and trade history are untouched; schema validation guarantees at least one tracked asset remains.

Args: symbol: yfinance ticker currently in the tracked list.

Returns: The updated tracked list, or {"status": "error", "error": ...}.

prepare_committeeA

Step 1 of the agent-run committee (Coordinator path): get everything YOU need to play the 4 roles yourself — no backend LLM key involved.

Returns the deterministic data blocks (regime, sentiment / defense flag, valuation, macro, events, portfolio, path reference) plus the 6 role prompts and instructions describing the 3 rounds. Run Macro / Quant / Risk (cheap subagents are fine), write the CIO memo yourself, then call submit_committee with the full transcript.

The backend keeps its own copy of the deterministic facts from this call and uses them when you submit (defense downgrade, regime, path snapshot), so a fact you forget to paste cannot silently switch a rule off. Submit within 6 hours of preparing.

submit_committeeA

Step 2 of the agent-run committee: hand in the transcript you produced from prepare_committee. The backend parses the CIO memo, applies the same deterministic rules as the backend-run committee (single-investment cap, defense downgrade, sanity checks), saves the decision and returns it.

If the CIO section has no parseable verdict, nothing is saved and this returns an error — fix the CIO section and submit again.

Returns: decision_id, the post-rule verdict object, saved path and facts_source ("prepare" = rules used the facts saved at prepare time; "transcript" = no recent prepare found, facts were read from your text).

run_committeeA

Run the 4-role LLM investment committee on a symbol (Direct path): Macro Strategist, Quant Analyst, and Risk Officer debate from isolated evidence, then a CIO synthesizes one calibrated BUY/HOLD/SELL-style verdict with a written memo.

Requires a backend LLM key (e.g. DEEPSEEK_API_KEY) and takes 30-90s on a cache miss. If the symbol was already analyzed today, the cached verdict is returned instantly unless force is set. Sends MCP progress notifications per debate phase when the client asks for them. Decision support only — the human always executes.

Args: symbol: Any yfinance ticker (US / HK / A-share / ETF / crypto / commodities), e.g. "AAPL", "GC=F", "510300.SS". force: Re-run even if a verdict already exists for today. max_rounds: Cross-challenge debate rounds (default 1).

Returns: Object with decision_id, cached flag, verdict and confidence_lookup (show this to the user instead of the self-reported confidence). The shape differs by path: - cached: false (fresh run): verdict is an object (verdict, confidence, suggested allocation, ...). - cached: true (today's transcript): verdict is the verdict string, with confidence, alloc_cny, alloc_currency alongside, plus the CIO memo as cio_memo and the deterministic input_health block (empty inputs, rewrite rules applied, forced HOLD) — no need to call explain_decision just to read them.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.1/5.0

Scored across 36 tools

Disambiguation4/5

Most tools have clearly distinct purposes, well separated by descriptions: the ledger ops (buy, sell, record_dividend, record_split, etc.), the committee paths (prepare/submit/run), and analysis tools (status, rebalance_plan, what_if) do not collide. The main soft overlap is among read-ledger tools (history, decisions, discipline, explain_decision) and between strategy vs set_allocations vs status, but the descriptions differentiate them adequately.

Naming Consistency4/5

The majority follow a predictable snake_case verb_noun or resource pattern (add_news_source, remove_news_source, record_fee, set_allocations, track_asset, untrack_asset, record_split). Read-only tools are bare nouns (strategy, history, status, doctor, live_prices), which is a minor but readable deviation rather than a chaotic mix.

Tool Count3/5

36 tools is heavy and above the comfortable 3-15 band, but the surface legitimately spans several distinct subdomains (portfolio ledger, fund orders, committee workflow, news pipeline, strategy config, reporting), so each tool roughly earns its place rather than being redundant.

Completeness5/5

The surface is remarkably complete: full portfolio lifecycle (buy/sell/deposit/withdraw/dividend/split/fee/ROC/fund orders), strategy configuration (set_allocations, track/untrack, read strategy), committee end-to-end (prepare/submit/run/decisions/explain/record_execution), and news ingestion. No obvious dead ends for the stated investment-assistant purpose.

Maintenance

ActivityMaintained
ResponsivenessWithin a week