Skip to main content
Glama

openInvest

A self-hosted investment decision engine built for modern AI agents. Multi-agent information isolation and cross-challenge protocol, providing an auditable decision trail (Audit Trail).

Python Agents License Stars Glama MCP server

๐Ÿ“š Full Architecture Wiki ยท ๐Ÿ‡จ๐Ÿ‡ณ ไธญๆ–‡็‰ˆ


What is OpenInvest?

OpenInvest is a self-hosted investment decision engine built for modern AI agents.

It provides a verifiable investment committee, evidence-based reasoning, long-horizon backtesting, and auditable decision records. Instead of replacing Claude Code, Codex, Hermes, or OpenClaw, OpenInvest is designed to power them.


Related MCP server: Decker

Live Performance & PnL

  • Benchmark Portfolio: The system introduces 8 standard control benchmarks across 4 quadrants (AI advisors / Mutual funds / Wealth management / Broad market index). For details on the comparison methodology and data cleaning logic, see docs/wiki/README.md.


Research & Falsification

System Self-Disclosure: This system is an auditing tool to eliminate human investment cognitive biases and enforce reasoning transparency, not a return-amplifying black box. Latest automated audit (docs/verdict_accuracy.md): Directional verdicts (excluding HOLD) have a true hit rate of 42.2% (n=56, below random); HOLD accounts for 56% of all decisions. The system's value lies in transparency and discipline (mostly staying inactive, low turnover), not directional prediction. Detailed log stream can be found in docs/verdict_accuracy.md.

This project systematically attempts to falsify its own edge and publishes negative results as-is. The deterministic features the committee reads, and the timing signals around them, were tested against pre-registered statistical gates โ€” none survived as tradable alpha.

Test

Result

Verdict

Q1 cross-sectional stock picking

6 features, mean-IC 0.025โ€“0.067, Holm-corrected p=0.397

No significant stock-picking signal

M1 multivariate GBM (out-of-sample)

mean OOS IC +0.003, p=0.925

Feature combination doesn't help either โ€” no signal

Q2 gold MA200 trend

p_holm=0.016, significant โ€” but trend_dca shows it is beta, not tradable alpha: timing terminal value 3.07 vs 15.10 buy-and-hold, Sharpe +0.36 vs +0.68, max drawdown deeper (โˆ’57% vs โˆ’44%)

Statistically significant, economically untradable

Per-asset multi-signal families

3 assets ร— 4 signal families ร— parameter grid = 24 variants per asset; after costs + DSR deflation, none passes DSR > 0.95

No tradable signal in any family

Positive control

A cheating perfect-foresight timing signal scores DSR = 1.00

The harness can detect a real signal

Methodology: Newey-West HAC t-statistics, Deflated Sharpe Ratio (Bailey & Lรณpez de Prado 2014, re-derived equation by equation), Holm correction, zero lookahead, and LLM training-cutoff probes.

Details: experiments/signal-eval/README.md ยท docs/verdict_accuracy.md ยท ADR-022 ยท ADR-023


Product Philosophy

Most AI investment assistants try to become better chatbots. OpenInvest instead builds a transparent, verifiable, and auditable decision engine that plugs into personal agents such as Claude Code, Codex, Hermes, and OpenClaw โ€” every improvement in those agents automatically makes OpenInvest more capable.

The division of labor is deliberate: your agent handles long-term memory, natural conversation, and user understanding; OpenInvest handles the verifiable investment committee, evidence-based reasoning, long-horizon backtesting, and auditable decision records.

                   User
                     โ”‚
         โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
         โ–ผ                       โ–ผ
    Your Agent             OpenInvest
(User Understanding)   (Market Understanding)
         โ”‚                       โ”‚
         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                     โ–ผ
            Better Investment Decisions

Your agent knows you. OpenInvest knows investing.

Avoiding User Ownership

OpenInvest intentionally avoids "owning" the user. Most AI products try to own everythingโ€”memory, persona, chat history, and workspaces. OpenInvest takes a back seat. It exposes clean APIs, CLI commands, and agent skills (Claude Code / Codex / Hermes / OpenClaw), letting your primary agent manage the conversation and context while OpenInvest powers the underlying investment intelligence.


Features

  • Multi-Agent Investment Committee: Isolated analysis and round-rebuttal debate.

  • Coordinator-Worker Architecture: Prevents context contamination and role hallucination.

  • Information Isolation: Rigidly blocks quant and risk analysts from out-of-boundary contexts.

  • Auditable Decision Trail: Clean logs showing exactly "why" each decision was made.

  • Markdown-as-a-Database: Frontmatter (YAML) + Markdown (Body) as the single source of truth.

  • Long-Horizon Backtesting: Built-in test harness with lookahead bias protections.

  • Dreaming-Based Memory Consolidation: Nightly memory distillation to prevent context drift.

  • Self-Hosted / Zero-Cost: Powered directly by your local agent's reasoning resources.

  • Agent Skill: Lightweight plugin for Claude Code / Codex / Hermes / OpenClaw, with interactive bootstrap wizard.

  • Automated Deployment: GitHub Actions workflow to run the committee and email reports daily.


Quick Start

Add the lightweight skill from your agent's plugin registry. The host agent will automatically pull the core code and align dependencies on first run:

# Claude Code
/plugin marketplace add longsizhuo/openInvest
/plugin install invest@openinvest

# Codex
codex plugin marketplace add longsizhuo/openInvest
codex plugin add invest@openinvest

# Hermes Agent (official plugin catalog)
hermes plugins install openinvest --enable
# older Hermes without the catalog: hermes plugins install longsizhuo/openInvest/plugin --enable

# OpenClaw
openclaw plugins install clawhub:openinvest

Any other MCP client: register the MCP server from step 2 below (full walkthrough in the agent tutorial).

2. Standalone โ€” MCP server or CLI (no clone needed)

The backend ships on PyPI; ~/openInvest holds only your data:

# MCP (any MCP client; add --http for a remote streamable-HTTP server โ€” BETA)
claude mcp add openinvest -e INVEST_HOME=~/openInvest -- uvx openinvest-mcp

# or plain CLI
INVEST_HOME=~/openInvest uvx openinvest status

Send set up invest (or ๅธฎๆˆ‘ๅˆๅง‹ๅŒ– invest) to any skill-enabled AI terminal. The system will trigger an interactive bootstrap wizard to guide you through:

  1. Detecting the memory/ state storage path and .env configuration.

  2. 5-dimensional profiling (Legal name, Risk capacity, Debt structure, Initial holdings, and optional keys).

  3. Running static data migration to immediately generate your first asset exposure memo.

๐Ÿ’ก Zero-Cost Execution: In skill interactive mode, the committee's underlying reasoning relies entirely on the host agent's (e.g. Claude Code) reasoning pipeline. No third-party API Key is consumed. You only need to configure an API key when setting up automated crons or calling independent Web APIs.

For self-hosting details, see docs/QUICK_START.md. (The bundled Web GUI was retired on 2026-07-05 โ€” all capabilities are exposed via CLI/MCP; a standalone frontend may return later.)

3. Serverless Self-Hosting (GitHub Actions)

Run the committee automatically via GitHub Actions and receive daily digest emails.

โš ๏ธ Fork must be set to Private: State files (holdings, verdicts) will be committed back to your fork. Public forks will leak your private financial information.

  1. Fork this repository and change its visibility to Private (Settings -> Visibility).

  2. Run set up invest locally to generate the initial memory/ folder, then commit and push it to your private fork:

    git add -f memory/ && git commit -m "chore: init memory state" && git push
  3. In your fork's Settings -> Secrets and variables -> Actions, add the following Secrets:

    • LLM_API_KEY (or DEEPSEEK_API_KEY): API key to run the committee.

    • EMAIL_SENDER / EMAIL_PASSWORD: Gmail address + App Password.

    • DIGEST_EMAIL_TO: Recipient email address.

  4. Enable Workflows under the Actions tab. The workflow runs automatically at 10:00 AM (Beijing time) daily; you can also manually trigger daily-report via Run workflow.


Architecture & Multi-Agent Orchestration

openInvest does not run a mock debate in a single LLM session. The system enforces an Information Isolation Contract at the core/committee/ layer, orchestrating 4 independent LLM processes in a directed acyclic graph (DAG):

                [ Macro Data Injection ]
                           โ”‚
                 โ–ผ 1. Macro Alignment Context
             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
             โ”‚    Macro Strategist      โ”‚ (VIX / Interest rate spread / Currency momentum)
             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                 โ–ผ 2. Async Multi-Dimensional Scrutiny (Async DAG)
             โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
             โ–ผ                          โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚  Quant Analyst   โ”‚        โ”‚   Risk Officer   โ”‚
   โ”‚ (RSI / Momentum) โ”‚        โ”‚ (Concentration)  โ”‚
   โ”‚                  โ”‚        โ”‚                  โ”‚
   โ”‚ ๐Ÿ›‘ No Holdings   โ”‚        โ”‚ ๐Ÿ›‘ No Indicators โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
             โ”‚                           โ”‚
             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
             โ–ผ 3. Round 2 Rebuttal & Cross-Challenge
             โ”‚ Mutual feedback loop for signal correction
             โ–ผ
   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   โ”‚         Chief Investment Officer (CIO)       โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
             โ–ผ 4. Deterministic State Persistence
          [ BUY / ACCUMULATE / HOLD / TRIM / SELL ]
  1. Macro Strategist: Assesses the global macro landscape (VIX, yield curve spread, core currency matrix) to establish the portfolio's risk threshold.

  2. Quant Analyst: A pure mathematical momentum and technical indicator filter. Strictly blocked from knowing portfolio holdings to eliminate human attachment and loss-aversion biases.

  3. Risk Officer: Focuses entirely on tail risks (drawdown buffers, concentration limits, solvency multipliers). Strictly blocked from technical indicators to make objective asset exposure rulings.

  4. Round 2 Rebuttal: Quant and Risk analysts are fed each other's Round 1 reports in Round 2, challenging boundaries until signals converge or safety valves trigger.

  5. CIO (Chief Investment Officer): Synthesizes the audited reports and outputs a structured Verdict (BUY / ACCUMULATE / HOLD / TRIM / SELL) with a confidence level. No auto-order execution occurs; final action remains strictly up to the human auditor.

Key trade-offs behind this design are recorded as ADRs in docs/wiki/adr/ (24 to date), including rulings that overturned our own earlier designs โ€” ADR-007 retired the few-shot CIO route, and ADR-009 rejected TA-style analyst agents after a pre-registered experiment.


Core Design

  • Coordinator-Worker Pattern: Workers operate in isolated namespaces. Boundary constraints are hardcoded at the framework layer in Python to prevent attention contamination in large multi-role prompts.

  • Markdown-as-a-Database: The system uses Frontmatter (YAML) + Markdown (Body) as the single source of truth. Leveraging fcntl.flock process file locks and temporary atomic file replacement, it provides a tamper-proof investment audit trail natively tracked by Git.

  • Three-Phase Dreaming Consolidation: Distills daily decisions against actual market outcomes nightly (Light Sleep $\rightarrow$ REM $\rightarrow$ Deep Sleep) to consolidate long-term insights, preventing Large Language Model (LLM) context drift over long execution spans.


Configuration

The system defaults to DeepSeek endpoints and supports any standard OpenAI-compatible API. LLM provider setup and all tunable runtime overrides (ADR-017) are documented in docs/wiki/22-configuration.md.


Disclaimers & Backtest Limitations

  1. No Financial Advice: This system is a decision-support tool powered by LLMs. Output memos represent simulated reasoning based on deterministic data and do not constitute asset allocation advice.

  2. Backtest Time-Lock & Lookahead Guard: The backtest engine (scripts/backtest_runner.py) has a hardcoded safety valve: it rejects backtests for decision_date > 2024-06-30 by default (override with --allow-lookahead). Since mainstream foundation models have training cutoff dates around mid-2024, backtesting on later intervals introduces severe Lookahead Bias (model pre-training leakage). Parameter tuning, Optuna sweeps, and prompt optimization must run strictly on historical windows prior to June 30, 2024.


Acknowledgments

  • Equibles โ€” Optional data provider for A-share and Hong Kong financial statements, and a daily-price fallback when Yahoo Finance is unreachable. Yahoo Finance stays the default; set your own free EQUIBLES_API_KEY to turn it on (setup).

  • MiMo โ€” Special thanks to MiMo Quantitative Lab for sponsoring production-grade high-performance LLM inference (powering mimo-v2.5-pro long-horizon sweeps).

  • OpenClaw Dreaming Guide โ€” Theoretical foundation for the three-phase sleep-cycle memory distillation framework.


License

This project is licensed under the MIT License - see the LICENSE file for details.

Available Tools

36 tools
add_news_sourceA
Idempotent

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" / "ๅŠ ไธชๆ–ฐ้—ปๆบ".

NameRequiredDescriptionDefault
urlYesRSS/Atom feed URL (a real feed, not a webpage).
nameYesShort slug for the feed, [a-z0-9_] (e.g. 'wsj_markets').

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it discloses the proxy-bypass fetch path, the live-probe validation that rejects non-feed URLs, the idempotent return-existing behavior (consistent with idempotentHint=true), and the list cap. These are real operational traits an agent cannot infer from readOnlyHint/destructiveHint alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the action, then constraints, then the trigger phrase. Every sentence carries a distinct fact (validation, idempotency, cap) with no padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers validation/failure behavior, idempotency and the growth cap; an output schema exists so return-value detail is unnecessary. Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both params are already described, but the description adds non-obvious constraints not in the schema โ€” the URL must be http(s) on a public host and must parse as a feed. That meaningfully sharpens how 'url' should be supplied.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Add an RSS/Atom feed to the crawler's source list'), which is clearly distinct from siblings news_sources and remove_news_source. An agent can tell exactly what this creates without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit trigger phrasing ('Use when someone says "follow <site>'s news" / "ๅŠ ไธชๆ–ฐ้—ปๆบ"'), which grounds when to call it. It stops short of naming alternatives or when-not conditions (e.g., listing via news_sources, removal via remove_news_source), so it is clear context but not full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

buyA
Destructive

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": ...}.

NameRequiredDescriptionDefault
kindNoAsset kind tag: 'equity', 'etf', 'metal' (gold), 'crypto', 'bond', 'fund', 'other'.equity
priceYesExecution price per unit, in `currency`.
unitsYesQuantity bought; must be > 0.
symbolYesyfinance ticker, e.g. 'AAPL', '510300.SS'. Gold is 'GC=F' and must be booked per gram in CNY: units = grams, price = CNY/gram, currency='CNY', kind='metal', unit_label='ๅ…‹' (USD/oz bookings are rejected).
currencyNoCurrency of `price`, e.g. 'CNY', 'USD', 'AUD'. Omit to use the existing position's currency (CNY for a new position); a different currency than the position's is rejected.
unit_labelNoHuman display label for units (default '่‚ก', i.e. shares).่‚ก
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.
existing_positionNoNot supported on buy. For a position held before using openInvest call `record_existing_position`; passing true here returns an error instead of deducting cash.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, so the write/cash impact is partly covered. The description still adds real value beyond them: it is pure bookkeeping (no real orders are placed), it moves ledger cash, it requires user confirmation first, and it discloses the fund-settlement distortion. It does not cover edge cases like failure modes when cash is insufficient, but with annotations carrying the safety profile this is strong.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The prose is front-loaded with purpose and the routing caveats before the Args listing, and the Returns line is brief because an output schema exists. The Args section, however, duplicates the input schema nearly verbatim, which is expendable length even though each individual sentence is well-formed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter write tool with an output schema, the description covers everything an agent needs: what it does, what alternatives exist for the two important edge cases, the confirmation prerequisite, the gold special case, and idempotency on retry. Nothing material is left unstated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3; the Args block is largely a restatement of the schema's own parameter descriptions (gold ticker/units/currency, idempotency reuse, unit_label default). It adds minor framing value, such as tying `currency` omission to the existing position, but nothing the schema does not already say.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb and resource โ€” 'Record a buy in the local ledger' โ€” and immediately explains both branches (weighted-average add to an existing position, or new position for an unseen symbol). It also states what the tool is not: 'openInvest never places real orders,' which sharply separates it from a real brokerage order path.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing rules: pre-existing holdings go to `record_existing_position`, off-exchange China mutual funds go to `place_fund_order` + `confirm_fund_order`, and it explains why (buy would book them as instantly filled, distorting totals). It even specifies a pre-call obligation โ€” confirm symbol, units, and price with the user โ€” which is actionable usage guidance, not just context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cancel_fund_orderA
Destructive

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": ...}.

NameRequiredDescriptionDefault
order_idYesorder_id of an in-transit order (status 'placed').

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds substantive context: the amount returns to ledger cash, the side effect touches ledger cash so user confirmation is required, and the error return shape is disclosed. It stops short of covering idempotency or failure-recovery behavior, keeping it short of a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Scope, preconditions, and the alternative are front-loaded in the first two sentences, before the Args/Returns blocks. The Returns section partially duplicates the existing output schema, which is minor waste, but the overall structure is clean.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with an output schema already present, the description covers the state precondition, the side effect, the alternative tool, and the error case. Any remaining gaps are minor and would be covered by the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already explains that order_id is an in-transit order with status 'placed'. The description's 'The in-transit order to cancel' adds no meaning beyond that, so it sits at the baseline for a schema-documented parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Cancel an in-transit off-exchange fund order') with a precise qualifier ('that was never executed'). It explicitly distinguishes itself from the confirm/sell siblings by noting that confirmed orders hold shares instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit precondition ('Only orders still in transit can be cancelled'), names the alternative path for confirmed orders ('use `sell` to book a redemption'), and adds an operational directive ('Confirm with the user before calling'). Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

confirm_fund_orderA
Destructive

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": ...}.

NameRequiredDescriptionDefault
feeNoSubscription fee in CNY, taken out of the order amount (units = (amount - fee) / nav). Default 0.
navNoUnit NAV to confirm at. Omit to fetch the pricing day's published NAV (if it isn't published yet the call returns status 'pending_nav' and changes nothing).
order_idYesorder_id from place_fund_order / status.pending_fund_orders.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description says the tool is 'Safe to call twice' and that an already-confirmed order changes nothing, which is idempotent behavior, but annotations declare `idempotentHint: false`. It also frames the operation as safe/idempotent while `destructiveHint: true`, creating a direct annotation contradiction despite otherwise useful behavioral detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and the automatic-job caveat are front-loaded, and the edge-status details earn their place. However, the Args and Returns blocks duplicate schema/output-schema content, making it slightly longer than necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a state-changing financial operation, the description covers purpose, manual-use conditions, duplicate-call behavior, pending NAV, fee/NAV semantics, and status returns. An output schema exists, so detailed return-shape explanation is not needed; completeness is strong.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents `order_id`, `nav`, `fee`, defaults, and the pending-NAV behavior. The description's Args section largely restates those fields, adding little beyond the units formula already present in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names the exact operation and accounting effect: turning an in-transit fund order into shares at the pricing day's NAV. It clearly positions itself as the second leg after place_fund_order and is distinguishable from place_fund_order and cancel_fund_order.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says the `fund_confirm` job runs automatically every weekday evening and manual calls are only for supplying NAV/fee or confirming early. It also gives conditions for duplicate calls and unpublished NAV.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations: agent mode only reads today's submitted verdicts (nothing re-run), backend mode runs the committee itself, requires a backend LLM key, and takes minutes. It also discloses the `missing_verdicts` failure semantics. These auth, latency, and side-effect details explain why readOnlyHint=false and are exactly the context an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded in the first sentence and every subsequent sentence carries load-bearing workflow or failure information. Slightly dense (backticks, arrows, mode labels) and the bare "roles" step is ambiguous, but there is no filler to cut.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need not be re-explained, and the description covers the mode split, prerequisites, key requirement, latency, and failure handling. Nothing an agent needs to invoke this correctly is absent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing to disambiguate; baseline 4 applies. No parameter meaning is missing because the schema is empty.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Assemble") and resource ("today's daily report") and enumerates the report's contents (portfolio, verdicts, performance, holdings digest), plus the return artifact (`full_report` Markdown). This clearly distinguishes it from siblings like decisions, run_committee, and status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly separates two operating modes and gives the exact precondition for agent mode (run prepare_committee โ†’ roles โ†’ submit_committee for every target asset FIRST) versus backend mode. It also tells the agent what to do with `missing_verdicts` entries (treat as failure and report). No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

decisionsA
Read-only

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).

NameRequiredDescriptionDefault
daysNoLook-back window in days.
limitNoMax decisions listed, newest first; 0 = all.
symbolNoOnly this ticker (case-insensitive), e.g. 'GC=F'.
verdictNoOnly this verdict, e.g. 'ACCUMULATE', 'HOLD', 'TRIM'.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=true, and the description's 'Read-only' line merely repeats that. The genuine added value is behavioral: the list is capped at `limit` newest-first so a year of history doesn't flood context, while `count` and `summary` still cover every match โ€” a non-obvious pagination/aggregation contract the agent would otherwise have to guess.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the resource and its purpose, then use cases, then args and returns in clearly labeled blocks. The Returns block is partly redundant given the output schema exists, but the structure is scannable and every other sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter, zero-required read tool with a full output schema, nothing needed to invoke it correctly is missing: the agent knows the default window, the cap semantics, how to filter, and that aggregates cover all matches. Return-value detail is arguably redundant but not a gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description largely restates the schema (default 90 days, limit 0 = all, case-insensitive symbol, verdict examples) and adds only the 'newest first' ordering and the rationale for the cap, which is modest incremental meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource (the unified decision ledger) and enumerates its composition โ€” committee verdicts joined with rule interventions, executions/refusals with reasons, and outcome data โ€” plus an adoption-rate summary. This is clearly distinguishable from siblings like `history`, `discipline`, and `explain_decision`, which an agent can rule out from the text alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives concrete usage contexts via the quoted questions it answers ('how often did I follow the advice', 'which recommendations did I skip') and tells the agent to use `symbol`/`verdict` for single-asset or single-verdict questions. It never explicitly names an alternative tool or states a when-not condition, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

depositA
Destructive

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": ...}.

NameRequiredDescriptionDefault
amountYesAmount to add; must be > 0.
currencyYesISO-style currency code, e.g. 'CNY', 'USD', 'AUD'.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as a non-read-only mutation, and the description adds important context beyond them: no real payment system is connected, idempotency-key retry behavior is documented, and return behavior is summarized. It does not fully address the destructiveHint annotation or discuss reversibility/permissions, so it is strong but not complete.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and scope, then uses short Args/Returns sections. It is appropriately sized, though the Args and Returns sections partly duplicate the input and output schemas.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the toolโ€™s complexity, rich input schema, existing annotations, and output schema, the description provides everything an agent needs: it clarifies bookkeeping-only behavior, amount/currency expectations, idempotency retry semantics, and error/return shape at a high level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains currency format, amount constraints, and idempotency-key behavior in detail. The descriptionโ€™s Args section largely mirrors that information rather than adding substantial new semantics, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: โ€œRecord a cash deposit into the ledger,โ€ and clarifies scope with โ€œin any currencyโ€ and โ€œBookkeeping only.โ€ This is clearly distinguishable from sibling tools like withdraw, buy, or record_fee.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides useful context that this is bookkeeping-only and not connected to a real payment system, which implies when it should be used. However, it does not explicitly name alternatives or state when not to use this tool versus withdraw, buy, or other ledger mutation tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

disciplineA
Read-only

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).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so description adds value by detailing return structure (summary + markdown) and the specific metrics computed. Does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero waste. Front-loaded purpose, then usage, then return structure. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters, read-only annotation, and existence of an output schema, the description fully explains what the tool returns and its purpose without needing more detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters in input schema (100% coverage), so baseline is 4. Description does not need to add param info; it correctly focuses on behavior and return format.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the verb 'Get' and resource 'discipline ledger', specifying exact metrics (HOLD ratio, intercepted trades, money saved/lost). Distinguishes from siblings like 'decisions' and 'explain_decision' by focusing on blocked interventions and counterfactual value.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells when to use: when user asks 'what has the committee blocked' or 'is this tool actually helping'. Also marks as 'Read-only', which implies it should not be used for modifications.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

doctorA
Read-only

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).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, and the description adds value beyond that: it discloses a side effect ('makes one short HTTP probe to the configured LLM endpoint when a key is set') and explains the nuanced readiness semantics (optional_for_coordinator / optional_for_email, coordinator vs direct path). This is rich behavioral context not available from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded in the first sentence, and the remaining content is dense but mostly earns its place. The closing 'Returns:' block is somewhat redundant given an output schema exists, costing a little conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only health check with an output schema, the description covers everything an agent needs: when to call it, how to interpret `status`, the optional-check semantics, and the probe side effect. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the baseline is 4. There are no parameter semantics to clarify, and the description correctly does not fabricate any.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific resource and action โ€” a session health check โ€” and equates it to `run.sh doctor` for agents without shell access. It clearly distinguishes itself from siblings by defining what `status` values mean and what the tool's overall job is.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states explicitly that this is 'the first call of a session' and when to hand over to the `invest-setup` skill (`needs_setup`). It also clarifies that missing LLM key/mail credentials do NOT trigger `needs_setup`. It does not explicitly differentiate from the sibling `status` tool, but the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

explain_decisionA
Read-only

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).

NameRequiredDescriptionDefault
decision_idYes"<date>/<symbol>", e.g. "2026-07-03/GC=F" โ€” exactly as returned by the decisions tool.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

readOnlyHint already covers the safety profile, but the description adds meaningful behavioral context: which return fields to surface to the user (confidence_lookup over the raw confidence, transcript_markdown rendering) and that path_snapshot may be null. This goes beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by clearly labeled when-to-use, Args, and Returns sections makes it easy to scan. It is somewhat verbose and the decision_id format is repeated in both Args and the schema, but every section carries useful signal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool returning a complex multi-part object, the description supplies enough to invoke and interpret it, and an output schema exists as backup. Coverage of invocation, usage, and return handling is solid, though naming a sibling for the 'list decisions' case would fully close the loop.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents the decision_id format and example. The Args section largely restates that same '<date>/<symbol>' format, so the description adds little beyond the structured field. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: retrieve the full reasoning behind one committee verdict, enumerating the concrete artifacts (4-role debate transcript, CIO memo, path-probability snapshot). This clearly distinguishes it from sibling tools like decisions (list) and run_committee (execute).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete trigger phrasings ('why was today's verdict HOLD') and the audit scenario, which tells the agent exactly when to reach for it. It doesn't name a specific alternative tool or a when-not condition, so it falls short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historyA
Read-only

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.

NameRequiredDescriptionDefault
nNoMaximum number of recent trades to return.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true. The description adds the read-only label and details the return structure (trades with specific fields and committee verdict records), providing useful behavioral context beyond the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the main purpose. Every sentence adds value, and the docstring style for Args and Returns is well-structured without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one optional parameter, no nested objects) and the existence of an output schema, the description is sufficiently complete. It outlines what is returned without needing to detail the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with the parameter 'n' already described as 'Maximum number of recent trades to return.' The description repeats this and adds no additional semantics, so it meets the baseline for high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves 'the most recent trade records and committee verdict history.' It uses a specific verb ('Get') and resource, and distinguishes itself from siblings like 'live_prices' or 'status' by focusing on historical data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides usage context with example queries like 'what did I buy recently' and notes it is read-only. It does not explicitly mention when not to use or suggest alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingest_eventA
Idempotent

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.

NameRequiredDescriptionDefault
urlYesCanonical source URL (also the dedup key).
titleYesHeadline of the news item.
sourceNoPublisher name (e.g. 'Reuters') โ€” the news outlet.
stanceNoFor the holdings: 'risk', 'opportunity' or 'neutral'. Required with one_line_claim.
snippetNoShort excerpt or summary of the article body.
entitiesNoKey entities (countries, companies, central banks), lowercase.
severityNo'low', 'mid' or 'high'. Required with one_line_claim.
event_typeNoe.g. 'macro', 'policy', 'earnings', 'geopolitics', 'commodity', 'other'.
ingested_byNoYour own agent identity (e.g. 'hermes') for provenance; distinct from source.host-agent
published_atNoISO 8601 publication time, if known.
one_line_claimNoYour one-sentence factual summary. Fill this (plus stance and severity) to ingest without any backend model โ€” preferred.
affected_symbolsNoyfinance tickers the event materially affects, e.g. ['GC=F'].

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations: it explains that the tool requires a backend LLM key, is disabled in advisory mode, is idempotent over url/claim, and that a new holding-relevant event can trigger a rate-limited committee re-run whose id is returned as 'queued:<id>' awaiting the agent in pending_committees. That is rich, decision-relevant behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and the preferred invocation path, then organizes detail into Args and Returns sections. It is long, but for a 12-parameter ingestion tool with mode gating and an error path, nearly every sentence carries weight; a few clauses are mildly redundant with the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for the tool's complexity: it covers the preferred vs. fallback normalization, key requirement, idempotency, mode gating, error behavior, and the committee-trigger return semantics, so an agent can call it correctly and anticipate outcomes without reading the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter meaning the schema does not: the stance/severity/one_line_claim coupling and the preferred self-normalization bundle, plus the provenance distinction between ingested_by and source and the url-as-dedup-key role. It does not tie every parameter together, keeping it just below top marks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (feed/ingest) plus resource (finance news item) and the full downstream effect: graded, mapped to affected symbols, stored for committee RAG recall. It is clearly distinguishable from siblings such as news_sources, pending_news, and the committee tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use guidance (proactively feed news the self-hosted crawler misses, especially A-share/regional coverage) and names the alternative normalization path (self-normalize vs. rely on the backend model), including the failure mode when keyless. Exclusions are stated too: disabled in advisory mode.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

live_pricesA
Read-only

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true, and the description reinforces this ('Read-only; single batch, no arguments') rather than contradicting it. It adds genuine behavioral context beyond annotations: the fixed-instrument scope and the null-field semantics when an upstream quote is unavailable. It stops short of stating freshness/latency guarantees, so not quite a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and routing constraint are front-loaded in the first paragraph, which is ideal. The trailing 'Returns' block enumerates every key and duplicates what the output schema already documents, making it the one part that doesn't fully earn its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-argument read-only tool this is complete: scope, sibling routing, read-only guarantee, batch behavior, and null handling are all covered, and an output schema exists to carry the return structure. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so the baseline is 4. The description correctly states 'no arguments', which is consistent with the empty schema and leaves nothing ambiguous for the caller.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Fetch) and a precise, enumerated resource (spot gold, USDCNY/AUDCNY FX, NDQ.AX, VIX, TNX) as a fixed reference set. It also explicitly distinguishes itself from the sibling `status`, which covers the user's own positions. An agent can route correctly without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use (quick market context before analysis; user asks 'how is the market / what's the gold price') and an explicit when-not, naming the alternative tool (`status`) for user-held positions with the condition that selects it. No inference required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

news_sourcesA
Read-only

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true. Description adds context about built-in vs extra feeds and mentions related mutating tools, which is helpful but not extensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and resource, no redundancy. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and zero parameters, the description fully explains what the tool returns (list of sources with types). No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist; schema coverage is 100% (empty). Description correctly omits param details, as none are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the verb 'list' and resource 'news feed sources', clearly distinguishing between built-in defaults and user-added extras. References sibling tools add_news_source and remove_news_source to differentiate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use: when someone asks 'what news sources do you follow' or before adding/removing a source. Provides clear context for invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pending_committeesA
Idempotent

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.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true, destructiveHint=false, and readOnlyHint=false; the description usefully adds the 24h request expiry and the rule for when an item is considered done. However, it never explains why the tool is flagged non-read-only (does calling it claim or consume items?), leaving a real behavioral gap against its own annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with no filler, and the workflow instruction is front-loaded after the purpose. The opening sentence is a dense fragment with an awkward line break, which slightly hurts immediate parseability, but nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With zero parameters and an output schema present, the description does not need to describe return values, and it supplies the mode, workflow, completion rule, and TTL an agent needs to service the queue. The only missing piece is whether invoking it mutates state, which matters given readOnlyHint=false.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so the schema imposes no semantic burden and the baseline is 4. There is nothing about arguments the description could or should clarify.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the resource (pending committee re-runs) and its trigger conditions (requested by events or price moves) and the operating mode (agent mode). It is a fragment rather than a verb-led statement, but an agent can tell it is the queue of committee work items it must service. It stops short of naming a sibling like run_committee to sharpen the contrast.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit follow-up procedure: for each item run `prepare_committee`, then the roles, then `submit_committee`, plus the completion condition (a newer verdict for that symbol) and the 24h expiry. What it does not state is when to call this tool itself versus run_committee or pending_news, so routing guidance is inferred rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pending_newsA
Idempotent

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.

NameRequiredDescriptionDefault
limitNoMax items to return.
dismiss_urlsNoURLs you reviewed and judged irrelevant to the holdings; they won't be offered again.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true), and the description adds real context beyond that: the queue-draining behavior, the 48h expiry, and the fact that dismissal permanently suppresses the URL. It doesn't explain pagination or ordering, but the mutation and lifecycle semantics are well disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the purpose, then gives the per-item workflow in one compact thought. Efficient and well ordered, though the path-like parameter listing (`one_line_claim` / `stance` / ...) is slightly dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. Together with the annotations, the description covers the workflow, the sibling handoff, the queue lifecycle, and the expiry window โ€” everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so both limit and dismiss_urls are already documented. The description reinforces the intent of dismiss_urls (irrelevant items passed back), which is marginal added value over the schema's own 'they won't be offered again'. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource (news the backend fetched but did not normalize) and the reason it exists (reasoning is delegated to the agent). It is distinguishable from ingest_event and the other news siblings by scope: this is the raw intake queue, not the ingestion or source-management tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: call ingest_event for relevant items, pass irrelevant ones back as dismiss_urls. It also states the lifecycle condition (items leave the queue once ingested or dismissed, expire after 48h), so when-to-use and when-it-disappears are both answered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

place_fund_orderA
Destructive

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": ...}.

NameRequiredDescriptionDefault
noteNoFree-text note stored with the order and ledger row.
amountYesSubscription amount in CNY (cash deducted now); must be > 0.
symbolYesOff-exchange China mutual fund: 'FUND:<6-digit code>' (a bare 6-digit code is also accepted).
currencyNoCurrency of the amount; off-exchange funds are CNY.CNY
order_tsNoWhen the order was placed, ISO 8601 in Beijing time (e.g. '2026-10-19T14:30:00'); default now. Before 15:00 on a trading day the order is priced at that day's NAV, otherwise at the next trading day's. Pass the real time when back-filling an order placed earlier.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=true) by spelling out the actual ledger effect: cash is deducted now, the in-transit amount counts at face value so total assets don't move and there is no fake dip. It also discloses the confirm-date calendar limitation (Mondayโ€“Friday, no China holiday table), the lag_source, and the idempotency-key retry semantics, which is exactly the kind of side-effect detail an agent needs for a mutating tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and ledger effect, then supporting caveats, then args/returns. Efficient for the amount of information conveyed, though the Returns block is partially redundant given an output schema exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating, non-idempotent bookkeeping tool with 6 params, this covers side effects, timing/NAV rules, confirmation workflow, retry semantics, and the sibling used to confirm. With an output schema present, the extra return-value summary is harmless and nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the schema descriptions are more detailed than the description's Args block (e.g. the 15:00 NAV cutoff and the idempotency-key duplicate behavior live in the schema). The description restates symbol/amount/currency without adding format or edge-case meaning beyond what the schema already provides, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('record the first leg of an off-exchange fund purchase') and immediately draws the boundary that distinguishes it from siblings: 'Bookkeeping only โ€” openInvest never places orders.' An agent can tell it apart from buy/confirm_fund_order/record_execution without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context ('the user already placed' the order, confirm fund/amount/time before calling) and names the alternative path for confirmation (the `fund_confirm` job or `confirm_fund_order`). It stops short of explicitly excluding the look-alike `buy` tool, so routing is good but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

prepare_committeeA
Idempotent

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.

NameRequiredDescriptionDefault
symbolYesA symbol already in strategy target_assets, e.g. 'GC=F', 'NDQ.AX'.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description discloses genuinely important behavior: the backend retains its own copy of the deterministic facts and reuses them at submit time (defense downgrade, regime, path snapshot) so omitted facts can't silently disable a rule, and the prepared data expires after 6 hours. This is exactly the kind of stateful/expiry/auth-adjacent context the annotations cannot convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The step-by-step structure is front-loaded with the purpose and then the sequence, and each statement adds value. It runs a bit long with parentheticals, but nothing is truly wasted given the multi-step workflow described.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex prep tool with no output schema, the description enumerates the returned payload (regime, sentiment/defense flag, valuation, macro, events, portfolio, path reference, the 6 role prompts, and instructions for the 3 rounds), which is exactly what an agent needs to proceed. Nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and there is a single well-documented parameter, so the schema already carries the semantics. The description adds no syntax or format guidance for `symbol` beyond what the schema states, making a baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb+resource+scope: 'Step 1 of the agent-run committee (Coordinator path): get everything YOU need to play the 4 roles yourself.' It distinguishes itself from sibling paths by explicitly ruling out a 'backend LLM key' and by naming the follow-up tool submit_committee, so an agent can place it relative to run_committee and submit_committee immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear sequencing: run Macro/Quant/Risk subagents, write the CIO memo, then call submit_committee, plus a concrete 6-hour submission window. It never explicitly states when NOT to use it versus the alternative run_committee path, so the choice between the two coordinator/backend paths is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rebalance_planA
Read-only

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": ...}.

NameRequiredDescriptionDefault
modeNocash_only: buy underweights with cash above the target cash ratio, never sell. hybrid (default): use that cash first, sell overweights only to cover the shortfall. sell_to_rebalance: sell every overweight back to target and buy underweights with the proceeds plus spare cash.hybrid
band_pctNoDrift band in percentage points (default 5): holdings within ยฑband of target are left alone.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds substantial behavior beyond readOnlyHint: it places no order, makes no LLM call, explains target sourcing, equal-split fallback, lot-size rules, and return/error shape. This is rich context for a read-only planning tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads what the tool computes and the key no-order boundary, then provides useful usage and return details. It is somewhat long, and the returns section is partly redundant because an output schema exists, but overall it is structured and mostly earns its space.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich input schema, output schema, and readOnlyHint annotation, the description covers the remaining agent-relevant context: target allocation sourcing, lot-size constraints, human execution, no LLM call, and error returns. Nothing critical is missing for correct selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters already have detailed schema descriptions, including mode semantics, defaults, and band_pct range. The description repeats the mode/band basics rather than adding much parameter-specific meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: compute a rebalance list against target allocation, with explicit scope that it only produces BUY/SELL/NONE recommendations and places no orders. This clearly distinguishes it from execution-oriented siblings such as buy, sell, and record_execution.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit user-question triggers ('do I need to rebalance', 'how far am I from target', 'what should I buy/sell'). It also clarifies the human-execution boundary, though it does not explicitly name all relevant alternatives such as what_if for scenario analysis.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_dividendA
Destructive

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": ...}.

NameRequiredDescriptionDefault
kindNo'dividend' (default) or 'interest' (money-market / cash-account interest).dividend
noteNoFree-text note stored with the ledger row.
amountYesGross amount before withholding tax (for kind='interest': the interest credited); must be > 0.
symbolNoyfinance ticker the dividend belongs to (required for kind='dividend'; optional for interest = account-level).
currencyYesCurrency the cash was credited in, e.g. 'CNY', 'USD', 'AUD'.
reinvestNoDRIP: use the net cash to buy more of `symbol` (adds a second ledger row, source='drip'). The holding must exist and be in `currency`.
trade_dateNoDate the event happened, YYYY-MM-DD (default: today). Account performance books it on this date, so pass the real date when back-filling history.
tax_withheldNoTax already withheld at source (kind='dividend' only); cash credited = amount - tax_withheld.
reinvest_priceNoReinvestment price per unit. Omit to use the stored raw close for the date (run `backfill_raw_close` first).
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false), the description discloses rich behavioral detail: exactly how cash is credited, that positions are unchanged, that it counts as account return inside NAV, that it is bookkeeping-only and never moves money, that a non-held/ledger symbol is rejected, and how the idempotency_key produces a duplicate response on retry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded: the core effect appears in the first sentence, followed by a confirmation directive, then an Args block and a brief Returns note. It is somewhat long because the Args section duplicates the 100%-covered schema descriptions, but the structure remains clear and each section is purposeful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (10 parameters, mutation with ledger effects, idempotency, reinvestment, typo guard), the description covers all necessary context. An output schema exists, so the minimal 'Returns' line is sufficient without describing return values in detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all ten parameters. The description largely restates those schema descriptions (e.g., amount > 0, tax_withheld formula, reinvest meaning) and adds only minor emphasis, so it does not meaningfully extend parameter semantics beyond the structured data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource ('Record a dividend (or interest)') and immediately clarifies the accounting treatment ('credits ledger cash by amount - tax_withheld, positions unchanged'). It also distinguishes the action from a sibling concept by explicitly saying it 'counts as account return (inside NAV), not as a deposit.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly scopes usage to dividends or interest 'the user already received' and adds a prerequisite ('Confirm symbol, gross amount, withholding tax, and the date with the user before calling'). It rules out deposit-like behavior and warns about the typo guard, but does not name or route to alternative sibling tools for other income events (e.g., record_return_of_capital).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_executionA
Idempotent

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": ...}.

NameRequiredDescriptionDefault
reasonNoThe user's stated reason (especially when declined).
executedYesTrue if the user acted on the verdict, False if they declined.
trade_idsNoOptional trade record IDs to link explicitly.
decision_idYes"<date>/<symbol>" from the decisions tool output.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description complements the annotations by explaining the idempotent behavior: 'replay the same record is a no-op, so retries are safe'. It also notes that the tool appends to the execution ledger and returns the stored record or error, providing full behavioral disclosure beyond the annotations' flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: first sentence states purpose, then behavioral note, usage guidance, Args, and Returns. Every sentence serves a purpose, and the structure is easy to parse. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 4 parameters (2 required), an output schema, and annotations, the description covers all necessary context: purpose, when to call, how to handle edge cases (decline), parameter details, and return value format. It is complete for effective agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds value by explaining the format of `decision_id` ("<date>/<symbol>") and the context for `reason` (especially when declined). While the Args section is somewhat redundant with the schema, it provides a clear, contextual listing that helps the agent understand parameter relationships.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the verb 'Record' and the resource 'execution of committee verdict'. It distinguishes itself by specifying the scope (whether the user executed or declined) and mentions idempotency and retry safety, which are unique traits among siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-call scenarios: 'when the user says "I bought it / I didn't buy / I disagree"'. It also gives specific guidance for the decline case: ask one short question for the reason first, referencing the sibling tool `decisions` and the adoption-rate loop.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_existing_positionA
Destructive

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": ...}.

NameRequiredDescriptionDefault
kindNoAsset kind tag: 'equity', 'etf', 'metal' (gold), 'crypto', 'bond', 'fund', 'other'.equity
priceYesAverage cost per unit, in `currency`.
unitsYesQuantity held; must be > 0.
symbolYesyfinance ticker, e.g. 'AAPL', '510300.SS'. Gold is 'GC=F' and must be booked per gram in CNY: units = grams, price = CNY/gram, currency='CNY', kind='metal', unit_label='ๅ…‹' (USD/oz bookings are rejected).
currencyNoCurrency of `price`, e.g. 'CNY', 'USD', 'AUD'. Omit to use the existing position's currency (CNY for a new position); a different currency than the position's is rejected.
unit_labelNoHuman display label for units (default '่‚ก', i.e. shares).่‚ก
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations covering readOnly=false/destructive=true, the description adds substantial behavior the annotations cannot convey: no cash is touched, history is tagged `funding_source: external_funding` / `source: mcp:existing_position`, duplicate calls double-count unless retried with the same idempotency key, and the symbol is not added to the tracked list. This is consistent with idempotentHint=false rather than contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose paragraph is well front-loaded and high value, but the trailing Args/Returns block repeats schema descriptions verbatim (units, price, currency, kind, unit_label, idempotency_key) at 100% coverage, inflating an otherwise tight definition for no new information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still surfaces the error envelope; combined with the cash-neutrality guarantee, duplicate-counting hazard, gold booking convention, and alternatives, nothing material an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters (including the gold-in-CNY-per-gram rule and the idempotency_key semantics) are already documented in the schema. The Args block largely restates those same descriptions, adding little that isn't already structured, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (record an already-held position) with its precise niche: onboarding backfill, no ledger cash movement. It explicitly distinguishes itself from `buy` (new purchase from cash) and `track_asset` (committee coverage), so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit when (positions the user held before openInvest, not yet in `status`) and an explicit when-not (calling it for a symbol already in `status` adds units again โ€” double count). It also names the two alternative tools and the conditions that select them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_feeA
Destructive

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": ...}.

NameRequiredDescriptionDefault
kindNo'fee' (default: account / remittance / standalone commission) or 'tax' (e.g. dividend tax settled afterwards).fee
noteNoFree-text note stored with the ledger row.
amountYesAmount paid (positive number); must be > 0.
symbolNoTicker the fee/tax relates to (optional; omit for account-level).
currencyYesCurrency the cash left in, e.g. 'CNY', 'USD', 'AUD'.
trade_dateNoDate the event happened, YYYY-MM-DD (default: today). Account performance books it on this date, so pass the real date when back-filling history.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and idempotentHint=false, but the description adds the actual failure mode ('fails if the currency's cash balance is lower than the amount'), the ledger semantics (cash debited, positions untouched, inside NAV), and the human-confirmation requirement. It slightly softens the non-idempotent annotation by describing conditional safety via idempotency_key without reconciling the two, which is a minor gap rather than a contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the accounting distinction and the failure condition, then a compact Args/Returns block. The Args section duplicates schema text almost verbatim, which is mild waste, but the overall structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what matters for a destructive mutation: prerequisite confirmation, the cash-balance failure condition, what is and is not affected, and idempotent retry behavior. With an output schema present it doesn't need to explain return values, though it does so briefly anyway.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented, including the enum for kind and the idempotency_key retry semantics. The Args block mostly restates the schema ('must be > 0', 'YYYY-MM-DD') and adds little syntax or format detail of its own, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('Record a fee or a tax the user already paid') and immediately scopes the accounting effect: 'debits ledger cash, positions unchanged. It is an account cost (inside NAV), not a withdrawal.' That explicitly separates it from withdraw and from buy/sell siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-not guidance: trade commissions need no separate entry because buy/sell already book them, and it is not a withdrawal. It also imposes a procedural rule the agent must follow โ€” confirm amount and date with the user before calling โ€” which is the kind of routing detail siblings can't express.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_return_of_capitalA
Destructive

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": ...}.

NameRequiredDescriptionDefault
noteNoFree-text note stored with the ledger row.
amountYesCash received as return of capital; must be > 0.
symbolYesyfinance ticker of an existing holding.
currencyYesCurrency received; must equal the holding's cost currency.
trade_dateNoDate the event happened, YYYY-MM-DD (default: today). Account performance books it on this date, so pass the real date when back-filling history.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only generic annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false), the description carries the real burden and does: it explains the exact ledger effect (credits cash, lowers average cost by amount/units, units unchanged), the floor-at-0 edge case, how excess is surfaced as excess_over_cost (capital gain), and the retry semantics of idempotency_key including the 'duplicate' response. This is substantive disclosure well beyond what the annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The behaviorally important material (mutation effect, cost floor, confirmation prompt) is front-loaded before the Args/Returns sections, which is good. The Args block duplicates the schema nearly verbatim, costing some space, but nothing is misleading and the prose is tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a mutation tool with rich annotations and an existing output schema, the description supplies everything an agent needs: the precise accounting effect, the excess-over-cost special case, the required user confirmation, and idempotent-retry guidance. Nothing material is left undefined.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents each parameter thoroughly (including the detailed idempotency_key semantics). The description's Args block largely restates that information, adding only marginal framing ('must match the holding's cost currency'), so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ('Record a return of capital'), scopes it to 'some ETF / REIT distributions', and immediately distinguishes it from income events by noting it is 'a cost reduction, not income' โ€” enough to separate it from siblings like record_dividend or record_fee without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear precondition ('Confirm symbol, amount, and date with the user before calling') and the qualifying context ('some ETF / REIT distributions', 'not income'), which implies when this tool applies versus a dividend recorder. It stops short of explicitly naming an alternative tool or stating a when-not-to-use case, so it lands just below the top.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_splitA
Destructive

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": ...}.

NameRequiredDescriptionDefault
noteNoFree-text note stored with the ledger row.
ratioYesNew shares per old share: a 10-for-1 split is 10, a 1-for-10 reverse split is 0.1. Must be > 0 and not 1.
symbolYesyfinance ticker that split (must be held now or appear in the ledger).
trade_dateNoEx-date of the split, YYYY-MM-DD (default: today). Pass the real ex-date when back-filling: account performance uses it to restate earlier trades.
ledger_onlyNoOnly write the ledger row, leave the holding's units / average cost untouched. Use it when the snapshot already reflects the split (e.g. you fixed the units by hand, or later trades were booked in post-split units).
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructiveHint=true and idempotentHint=false; the description is consistent with both and adds real context: it rewrites units and average cost, the rejection condition, and the duplicate-return behavior when reusing an idempotency_key. Return shape is mentioned but an output schema already covers that, so it is a modest addition rather than a gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core behavior and mutation warning, then the rejection rule, then a caution. The trailing Args/Returns block duplicates the JSON schema descriptions verbatim, which is redundant, but the prose paragraphs themselves are tight and every sentence carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, non-idempotent mutation with 6 parameters, the description covers the arithmetic effect, the confirmation requirement, the double-apply hazard, the rejection condition with its workaround, and retry semantics. An output schema exists, so the brief Returns line is sufficient rather than insufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all six parameters, and the Args block largely restates it. What the description adds beyond the schema is the derived semantics โ€” that units multiply by ratio while average cost divides by it, with cash untouched โ€” which tells the agent the actual effect of the ratio value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Record a stock split / reverse split") and immediately gives the arithmetic effect: units x ratio, average cost / ratio, cash unchanged. This clearly separates it from sibling mutation tools like record_dividend, record_return_of_capital, and record_fee.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to call it once per split and warns that a second call multiplies the position again. It also names the precondition that causes rejection (existing trades/corrections on or after trade_date) and the escape hatch (ledger_only=true), plus a confirmation-before-calling instruction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_news_sourceA
Destructive

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

NameRequiredDescriptionDefault
keyYesFeed name or URL to remove (extra feeds only; defaults can't be removed).

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as destructive (destructiveHint: true). The description adds specific behavioral context: only user-added feeds can be removed, default feeds are protected. This goes beyond the annotation's binary flag.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with the main purpose, followed by a key limitation. No unnecessary words or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description adequately covers the tool's function and main constraint for a simple delete operation. With an output schema present, return values are not needed. Minor gap: no mention of behavior for non-existent keys or confirmation requirements.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a description for the 'key' parameter that already specifies it can be a feed name or URL and excludes defaults. The tool description adds no additional semantic value beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description uses specific verb 'Remove' and resource 'user-added news feed', clearly distinguishing from sibling tools like add_news_source and news_sources. It also explicitly states that built-in default feeds cannot be removed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description indicates when to use (remove user-added feeds) and when not (defaults cannot be removed). It provides clear context but does not explicitly name alternative tools for adding or listing feeds, though those are implied by sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_committeeA
Idempotent

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: Symbol to analyze. Listed assets use yfinance tickers: US "AAPL", A-share "603083.SS" (Shanghai) / "000001.SZ" (Shenzhen), HK "0700.HK", exchange ETF "510300.SS", crypto "BTC-USD", futures "GC=F". China off-exchange (OTC) mutual funds use "FUND:<6-digit code>", e.g. "FUND:110011". A bare 6-digit code is rejected โ€” add the suffix or the FUND: prefix. 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.

NameRequiredDescriptionDefault
forceNoRe-run even if a verdict already exists for today.
symbolYesSymbol to analyze. Listed assets use yfinance tickers: US 'AAPL', A-share '603083.SS' (Shanghai) / '000001.SZ' (Shenzhen), HK '0700.HK', exchange ETF '510300.SS', crypto 'BTC-USD', futures 'GC=F'. China off-exchange (OTC) mutual funds use 'FUND:<6-digit code>', e.g. 'FUND:110011'. A bare 6-digit code is rejected โ€” add the suffix or the FUND: prefix.
max_roundsNoCross-challenge debate rounds.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well past annotations: discloses the hard dependency on a backend LLM key, the 30-90s cache-miss latency, caching semantics keyed to the day plus `force`, and streaming progress notifications per debate phase. It also adds a safety framing ('Decision support only โ€” the human always executes') and warns that `confidence_lookup` should supersede the self-reported confidence, which the annotations say nothing about.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose and latency/caching caveats are front-loaded in the first two paragraphs, and the Args/Returns structure is easy to scan. It is somewhat long and the Args block duplicates schema text that is already 100% covered.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers everything an agent needs before calling: symbol formatting edge cases (bare 6-digit code rejected, FUND: prefix), auth dependency, latency, cache-busting, and the fact that the return shape differs between cached:false and cached:true including the input_health block. Even with an output schema present, the path-dependent shape difference is essential context that the schema alone would not convey.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so every parameter is already documented; the description's Args block largely restates the symbol and force text verbatim and adds only the effective default for max_rounds. A baseline 3 is appropriate when the schema carries the full parameter burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('Run the 4-role LLM investment committee on a symbol') and spells out the roles and the output (a CIO-synthesized BUY/HOLD/SELL memo). The '(Direct path)' label hints at a staged alternative but never names prepare_committee/submit_committee, so sibling differentiation is implied rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear operating context: a backend LLM key is required, a fresh run takes 30-90s, and today's cached verdict is returned unless `force` is set. It also steers the agent away from a sibling ('no need to call explain_decision just to read them'). What's missing is an explicit statement of when to prefer the staged/alternate committee path over this direct one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sellA
Destructive

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": ...}.

NameRequiredDescriptionDefault
priceYesExecution price per unit, in the holding's cost currency.
unitsYesQuantity sold; must be > 0.
symbolYesyfinance ticker of an existing holding.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true and idempotentHint=false, but the description adds substantive context beyond them: which ledger fields change (units down, average cost unchanged, cash credited in cost currency), the warning that cash moves, and the retry/dedupe behavior of the idempotency key. No contradiction with the annotations โ€” a fresh call with a new key legitimately sells more, consistent with idempotentHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the ledger effect and the pre-call confirmation, then organizes details under Args/Returns headings. Slightly redundant with the schema's parameter descriptions, but every section earns its place for a cash-moving mutation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, cash-affecting mutation with an output schema present, the description covers what the tool does, what it alters, the confirmation requirement, and retry semantics. Nothing an agent needs in order to call it safely is missing, and return values needn't be expanded since the output schema exists.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters including idempotency_key semantics are already documented in the schema. The Args block largely restates those same definitions with no added syntax, format, or edge-case guidance. Baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Record a sell in the local ledger') and immediately describes the ledger effect: reduces units with average cost unchanged, credits cash in the holding's cost currency. It also distinguishes itself from order-placing siblings by stating openInvest never places real orders, so an agent can tell it apart from place_fund_order or record_execution.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit pre-call guidance ('Confirm symbol, units, and price with the user before calling; this moves ledger cash') and scopes the tool to bookkeeping already-executed trades, which routes the agent away from real-order tools. It stops short of naming a specific sibling to use instead in ambiguous cases, so it is strong but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_allocationsA
Idempotent

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": ...}.

NameRequiredDescriptionDefault
alertsNoPer-asset alert lines as {symbol: {rule: value}}, rule in price_above / price_below / day_drop_pct / day_rise_pct / drawdown_from_cost_pct, e.g. {'GC=F': {'price_below': 900, 'day_drop_pct': 2}}. Rules you name overwrite, a null rule value clears just that rule, rules you don't mention stay; a null for the whole symbol clears all its alerts. Symbols must already be tracked. *_pct values are percentage points (3 = 3%), unlike target_pct. Alerts are only delivered when INVEST_EVENT_ALERT=1 is set on the server.
target_pctsNoPer-asset target weights as {symbol: fraction of total assets in [0, 1]}, e.g. {'510300.SS': 0.3, 'GC=F': 0.2}. Symbols must already be tracked (see track_asset). A null value clears that asset's target (back to an equal split). The weights must sum to <= target_allocation_stock (the new one if you pass it in the same call).
target_allocation_cashNoCash weight in [0, 1], e.g. 0.3. Pass together with target_allocation_stock; omit both to leave the split unchanged.
target_allocation_stockNoStock weight in [0, 1], e.g. 0.7. Pass together with target_allocation_cash (they must sum to ~1.0); omit both to leave the stock/cash split unchanged.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare mutation (`readOnlyHint: false`), idempotency, and non-destructiveness, but the description adds substantial behavioral context: writes are validated and atomic, invalid writes roll back, clearing semantics differ for rules vs whole symbols, and alerts are only delivered when `INVEST_EVENT_ALERT=1` is set.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and usage, then organized into Args and Returns. Some Args content duplicates the already rich schema descriptions, but the structure remains clear and the extra detail is not harmful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a mutation tool with four optional parameters, rich annotations, an output schema, and nested alert/target maps, the description supplies the remaining operational context: atomic validation, rollback behavior, sum constraints, and alert delivery prerequisites. Nothing critical appears missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents each parameter thoroughly, including examples, clearing behavior, and percentage-point semantics for alerts. The description's Args section largely restates those constraints rather than adding new parameter-level meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (update) and resource (strategy target allocation) with the exact fields affected: stock/cash ratio, per-asset target weights, and alert lines. It also names related consumers (`rebalance_plan` and the price sentinel), making the tool distinguishable from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete user-utterance examples such as 'set my target to 70% stock / 30% cash' and 'put 30% in 510300.SS and 20% in gold'. It also explains a key conditional workflow: lowering the stock target below current per-asset weights requires passing new weights in the same call. It does not provide explicit when-not-to-use guidance or name sibling alternatives for adjacent tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

statusA
Read-only

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).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint; the description adds the operationally important fact that it fetches live quotes so values change between calls โ€” an agent must know not to cache or compare stale snapshots. It also discloses degradation behavior (null price fields on unavailable quotes, {"status": "insufficient_history"} until two trading days of ledger exist) and conditional field presence, none of which is inferable from the annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Structure is good โ€” purpose, then when-to-use, then returns, front-loaded correctly. But the Returns block runs long for a zero-argument tool and largely re-enumerates fields the output schema already defines (fx, total_assets_cny, performance, income_30d, pending_fund_orders), burying the genuinely useful caveats (null quotes, is_tracking_only rows, insufficient_history) inside field-by-field detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity portfolio snapshot the description covers the full surface an agent needs: what is returned at a summary level, how missing quotes and tracking-only assets appear, the insufficient-history state, and that figures shift between calls. An output schema exists, so it is not required to enumerate returns โ€” doing so makes it more than complete, not less.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so there is no parameter semantics to explain; the baseline for a no-arg tool applies. Nothing in the description misdescribes or implies hidden inputs.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb and resource plus an enumeration of scope: cash per currency, units/avg cost/live price per holding, unrealized P&L per position and total. That is far more than a restatement of the name. It stops short of a 5 because it never names the overlapping siblings (live_prices, daily_report, history) that an agent might otherwise reach for when it just needs quotes or a summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete trigger phrases ("show my portfolio", "how is my P&L") and a forward-looking trigger ("before proposing any trade"), which is real routing guidance rather than implied usage. No exclusions or named alternatives, so it sits at a clear 4 rather than 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

strategyA
Read-only

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).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide readOnlyHint=true. The description adds context about the return value structure and the nightly Dreaming job, enhancing transparency beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-organized with clear sections and bullet points, though slightly verbose. Every sentence adds value, making it effective without being overly long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and an existing output schema, the description fully covers the tool's purpose, usage, and return structure. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so baseline 4 applies. The description does not need to add parameter information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it retrieves the user's investment strategy, including target allocation, tracked assets, and insights. This distinguishes it from sibling tools like set_allocations, track_asset, and untrack_asset.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly tells when to use: '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".' Also marks as read-only, differentiating from mutating tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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).

NameRequiredDescriptionDefault
modelNoModel that actually played the roles, e.g. 'claude-sonnet-5-5'; omitted -> recorded as 'unknown'. The scorecard buckets verdicts by provider:model.
symbolYesSame symbol you passed to prepare_committee.
providerNoWhich agent played the roles, e.g. 'hermes', 'claude', 'codex'.agent
transcriptYesAll sections, each starting with its separator line: === MACRO ===, === QUANT_R1 ===, === RISK_R1 ===, === QUANT_R2 ===, === RISK_R2 ===, === CIO ===.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=false / idempotentHint=false / destructiveHint=false, and the description is consistent with the mutation claim ('saves the decision'). It adds real behavior beyond annotations: the no-parseable-verdict error path, the deterministic rules applied, and the facts_source distinction. It does not clarify whether resubmitting creates a duplicate decision, which matters given idempotentHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the workflow step, then error handling, then returns. The Returns section restates what the output schema presumably carries, but the whole thing is compact and each section does useful work.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers the happy path, the error path, and the facts_source semantics, which is enough for an agent to call and recover correctly. With an output schema present, the returns prose is redundant, and the repeat-submission/idempotency question is left open.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents symbol, transcript sections, model, and provider. The description confirms the symbol must match prepare_committee but adds no syntax or constraint detail beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('hand in the transcript', 'Step 2 of the agent-run committee') and anchors itself to the workflow step, naming prepare_committee as the predecessor. An agent can distinguish it from prepare_committee and run_committee without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames itself as step 2 following prepare_committee and contrasts the agent-run path with the 'backend-run committee'. It also states the failure condition and remediation. It never explicitly says when to prefer run_committee over this path, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

track_assetA
Idempotent

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": ...}.

NameRequiredDescriptionDefault
symbolYesyfinance ticker to track, e.g. 'AAPL', '0700.HK', 'BTC-USD'.
channelNoWhere the user actually buys it (broker/app name).
target_pctNoTarget weight of this asset as a fraction of total assets, in [0, 1] (0.3 = 30%); read by rebalance_plan. The weights of all tracked assets must sum to <= target_allocation_stock, otherwise the write is rejected and the current sum is reported. Assets without one split the remainder equally. To clear a target use set_allocations with a null value.
display_nameNoHuman-friendly name shown in reports.
sell_fee_pctNoSell-side fee in percent, used by fee-aware math.
price_offset_pctNoSystematic offset between quote and actual fill price, in percent (e.g. bank gold spread).
alert_price_aboveNoAlert when the price reaches or exceeds this level. Same price basis as status.current_price (held: cost currency, gold booking = CNY per gram; tracked-only: the quote source's own price).
alert_price_belowNoAlert when the price falls to or below this level (same price basis as alert_price_above). Must be below alert_price_above if both are set.
alert_day_drop_pctNoAlert when the latest daily bar's drop vs the previous close reaches this many percentage points (3 = 3%, not a 0-1 fraction). On a closed market that is the last session; each trading day is reported once.
alert_day_rise_pctNoAlert when the latest daily bar's rise vs the previous close reaches this many percentage points (3 = 3%); each trading day is reported once.
max_single_invest_cnyNoPer-decision investment cap in CNY. On a new entry, defaults to the strategy-level max_single_invest_cny; optional on update.
alert_drawdown_from_cost_pctNoAlert when a held position is this many percentage points below its average cost (10 = 10%). Only evaluated for assets you hold.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false) by disclosing alert cooldowns (24h for price lines, once per trading day for day-move lines), that each passed alert line overwrites only that line, the target-weight sum rejection condition, and the server-side INVEST_EVENT_ALERT=1 delivery gate that silently degrades to logging. This is exactly the kind of non-obvious operational context the description should carry.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and usage sentences are front-loaded and earn their place, but the long Args section duplicates parameter descriptions already present at 100% schema coverage, adding bulk without new information for most fields.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter mutation with a full output schema, the description covers the mutation semantics, alert lifecycle, failure modes (weight-sum rejection), and the error return shape, leaving no significant gap an agent would need to guess at.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the Args block largely restates the schema descriptions verbatim, so baseline 3 applies. A few additions are real ('3 = 3%, not a 0-1 fraction' caveat, overwrite-per-line behavior), but most parameter meaning is already in the structured schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Add a symbol to the tracked-asset list, or update an existing entry') and immediately characterizes the operation as an idempotent upsert with per-field semantics. It clearly differentiates itself from untrack_asset and set_allocations, which it names explicitly for the clearing case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete trigger phrases ('track AAPL', 'alert me when X drops below N', 'tell me if it falls 3% in a day') plus the update cases (cap/channel/fees/target weight). It also routes the agent elsewhere for clearing a line ('use set_allocations with a null value'), so when-to-use and when-not-to-use are both covered.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

untrack_assetA
DestructiveIdempotent

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": ...}.

NameRequiredDescriptionDefault
symbolYesyfinance ticker currently in the tracked list.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true, idempotentHint=true), the description adds critical context: holdings and trade history are untouched, and schema guarantees at least one tracked asset remains.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short paragraphs, no redundancy, and front-loaded with the main action. Very efficient, though the Args and Returns could be integrated.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one parameter, good annotations, and mention of output schema, the description covers effects, safety, validation, and error handling fully.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description of the 'symbol' parameter. The description repeats the same info without adding new meaning, meeting the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs ('Remove', 'stop covering') and clearly identifies the resource ('tracked-asset list'). It distinguishes itself from the sibling 'track_asset' and other trading tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the action and notes a validation constraint (at least one asset remains), but does not explicitly provide when to use this tool versus alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

what_ifA
Read-only

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.

NameRequiredDescriptionDefault
pctNoHypothetical percent change, e.g. -10 for a 10% drop. Provide exactly one of pct or price.
priceNoHypothetical absolute target price (alternative to pct).
symbolYesyfinance ticker held or tracked by the user, e.g. 'NDQ.AX', 'GC=F', '510300.SS'.

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, and the description adds significant behavioral context: 'pure arithmetic over current holdings โ€” no LLM call, instant, free.' It clarifies the tool has no side effects, is fast, and free, which goes well beyond the annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a short intro, usage guidance, parameter explanations, and return description. It is front-loaded with the key purpose and contains no unnecessary words. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has only 3 parameters, an output schema exists, and the description covers purpose, usage, parameters, and returns, it is fully complete. Additional details like 'instant, free' provide useful context. No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, baseline is 3. The description adds value by reiterating the mutual exclusivity constraint 'Provide exactly one of pct or price' and clarifying the symbol parameter as 'yfinance ticker held or tracked by the user' beyond the schema's description. This earns a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Simulate portfolio P&L for a hypothetical price move' and distinguishes it from siblings by emphasizing it is a pure arithmetic simulation with no LLM call, instant, and free. This specificity and differentiation from tools like buy/sell/track earns a top score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use: 'when the user asks scenario questions like "if the Nasdaq drops 10%, how much do I lose"' and provides clear guidance on parameters: 'Provide exactly one of pct or price.' While it does not explicitly state when not to use, the context makes it clear for hypotheticals, so it earns a 4.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

withdrawA
Destructive

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": ...}.

NameRequiredDescriptionDefault
amountYesAmount to remove; must be > 0.
currencyYesISO-style currency code, e.g. 'CNY', 'USD', 'AUD'.
idempotency_keyNoOptional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {"status": "duplicate"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (destructiveHint=true, readOnlyHint=false, idempotentHint=false) it discloses the insufficient-balance failure mode, the bookkeeping-only scope, and dedup behavior on key reuse. The idempotency_key emphasis sits in mild tension with idempotentHint=false, though the annotation describes default no-key behavior, so it is not a contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening one-line summary is well front-loaded, but the Args block duplicates fields already fully covered by the schema, and the Returns line overlaps an existing output schema. Several sentences do not earn their place, diluting an otherwise tight core.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive ledger mutation with annotations and an output schema present, the description supplies the mutation intent, failure behavior, scope caveat, and idempotency guidance an agent needs to call it correctly. Return-value explanation is redundant given the output schema, but nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents currency, amount, and the idempotency_key dedup semantics in far more detail. The description's Args block largely restates the schema and adds no syntax or format information beyond it, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb + resource ("Record a cash withdrawal from the ledger") makes the operation unmistakable and distinguishable in nature from deposit/buy/sell siblings. It stops short of explicitly naming any sibling or routing rule, so it is clear but not sibling-differentiating.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when it applies (recording an outflow) and states a failure condition ("Fails if the balance is insufficient") and a scope caveat ("no real payment system is connected"). However it never says when to prefer this over deposit/buy/record_fee or how to sequence it, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.68.1
    • Changedrun_committee1 field changed
      • changedInput schema / properties / symbol / description
        Previous value: -"Any yfinance ticker (US / HK / A-share / ETF / crypto / commodities), e.g. 'AAPL', 'GC=F', '510300.SS'."New value: +"Symbol to analyze. Listed assets use yfinance tickers: US 'AAPL', A-share '603083.SS' (Shanghai) / '000001.SZ' (Shenzhen), HK '0700.HK', exchange ETF '510300.SS', crypto 'BTC-USD', futures 'GC=F'. China off-exchange (OTC) mutual funds use 'FUND:<6-digit code>', e.g. 'FUND:110011'. A bare 6-digit code is rejected โ€” add the suffix or the FUND: prefix."
  2. 22 tool updatesv0.45.1
    • Changedbuy3 fields changed
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {\"status\": \"duplicate\"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.",
        +  "title": "Idempotency Key"
        +}
      • changedInput schema / properties / kind / description
        Previous value: -"Asset kind tag, e.g. 'equity', 'etf', 'commodity'."New value: +"Asset kind tag: 'equity', 'etf', 'metal' (gold), 'crypto', 'bond', 'fund', 'other'."
      • changedInput schema / properties / symbol / description
        Previous value: -"yfinance ticker, e.g. 'AAPL', '510300.SS', 'GC=F'."New value: +"yfinance ticker, e.g. 'AAPL', '510300.SS'. Gold is 'GC=F' and must be booked per gram in CNY: units = grams, price = CNY/gram, currency='CNY', kind='metal', unit_label='ๅ…‹' (USD/oz bookings are rejected)."
    • Addedcancel_fund_order
    • Addedconfirm_fund_order
    • Addeddaily_report
    • Changeddeposit1 field changed
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {\"status\": \"duplicate\"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.",
        +  "title": "Idempotency Key"
        +}
    • Addeddoctor
    • Changedingest_event6 fields changed
      • addedInput schema / properties / affected_symbols
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "yfinance tickers the event materially affects, e.g. ['GC=F'].",
        +  "title": "Affected Symbols"
        +}
      • addedInput schema / properties / entities
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Key entities (countries, companies, central banks), lowercase.",
        +  "title": "Entities"
        +}
      • addedInput schema / properties / event_type
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "e.g. 'macro', 'policy', 'earnings', 'geopolitics', 'commodity', 'other'.",
        +  "title": "Event Type"
        +}
      • addedInput schema / properties / one_line_claim
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Your one-sentence factual summary. Fill this (plus stance and severity) to ingest without any backend model โ€” preferred.",
        +  "title": "One Line Claim"
        +}
      • addedInput schema / properties / severity
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "'low', 'mid' or 'high'. Required with one_line_claim.",
        +  "title": "Severity"
        +}
      • addedInput schema / properties / stance
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "For the holdings: 'risk', 'opportunity' or 'neutral'. Required with one_line_claim.",
        +  "title": "Stance"
        +}
    • Addedpending_committees
    • Addedpending_news
    • Addedplace_fund_order
    • Addedprepare_committee
    • Addedrebalance_plan
    • Addedrecord_dividend
    • Changedrecord_existing_position3 fields changed
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {\"status\": \"duplicate\"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.",
        +  "title": "Idempotency Key"
        +}
      • changedInput schema / properties / kind / description
        Previous value: -"Asset kind tag, e.g. 'equity', 'etf', 'commodity'."New value: +"Asset kind tag: 'equity', 'etf', 'metal' (gold), 'crypto', 'bond', 'fund', 'other'."
      • changedInput schema / properties / symbol / description
        Previous value: -"yfinance ticker, e.g. 'AAPL', '510300.SS', 'GC=F'."New value: +"yfinance ticker, e.g. 'AAPL', '510300.SS'. Gold is 'GC=F' and must be booked per gram in CNY: units = grams, price = CNY/gram, currency='CNY', kind='metal', unit_label='ๅ…‹' (USD/oz bookings are rejected)."
    • Addedrecord_fee
    • Addedrecord_return_of_capital
    • Addedrecord_split
    • Changedsell1 field changed
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {\"status\": \"duplicate\"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.",
        +  "title": "Idempotency Key"
        +}
    • Changedset_allocations15 fields changed
      • addedInput schema / properties / alerts
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": {
        +        "anyOf": [
        +          {
        +            "additionalProperties": {
        +              "anyOf": [
        +                {
        +                  "type": "number"
        +                },
        +                {
        +                  "type": "null"
        +                }
        +              ]
        +            },
        +            "type": "object"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Per-asset alert lines as {symbol: {rule: value}}, rule in price_above / price_below / day_drop_pct / day_rise_pct / drawdown_from_cost_pct, e.g. {'GC=F': {'price_below': 900, 'day_drop_pct': 2}}. Rules you name overwrite, a null rule value clears just that rule, rules you don't mention stay; a null for the whole symbol clears all its alerts. Symbols must already be tracked. *_pct values are percentage points (3 = 3%), unlike target_pct. Alerts are only delivered when INVEST_EVENT_ALERT=1 is set on the server.",
        +  "title": "Alerts"
        +}
      • addedInput schema / properties / target_allocation_cash / anyOf
        Added value: +[
        +  {
        +    "maximum": 1,
        +    "minimum": 0,
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / target_allocation_cash / default
        Added value: +null
      • changedInput schema / properties / target_allocation_cash / description
        Previous value: -"Cash weight in [0, 1], e.g. 0.3. Must sum to ~1.0 with stock."New value: +"Cash weight in [0, 1], e.g. 0.3. Pass together with target_allocation_stock; omit both to leave the split unchanged."
      • removedInput schema / properties / target_allocation_cash / maximum
        Removed value: -1
      • removedInput schema / properties / target_allocation_cash / minimum
        Removed value: -0
      • removedInput schema / properties / target_allocation_cash / type
        Removed value: -"number"
      • addedInput schema / properties / target_allocation_stock / anyOf
        Added value: +[
        +  {
        +    "maximum": 1,
        +    "minimum": 0,
        +    "type": "number"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • addedInput schema / properties / target_allocation_stock / default
        Added value: +null
      • changedInput schema / properties / target_allocation_stock / description
        Previous value: -"Stock weight in [0, 1], e.g. 0.7. Must sum to ~1.0 with cash."New value: +"Stock weight in [0, 1], e.g. 0.7. Pass together with target_allocation_cash (they must sum to ~1.0); omit both to leave the stock/cash split unchanged."
      • removedInput schema / properties / target_allocation_stock / maximum
        Removed value: -1
      • removedInput schema / properties / target_allocation_stock / minimum
        Removed value: -0
      • removedInput schema / properties / target_allocation_stock / type
        Removed value: -"number"
      • addedInput schema / properties / target_pcts
        Added value: +{
        +  "anyOf": [
        +    {
        +      "additionalProperties": {
        +        "anyOf": [
        +          {
        +            "type": "number"
        +          },
        +          {
        +            "type": "null"
        +          }
        +        ]
        +      },
        +      "type": "object"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Per-asset target weights as {symbol: fraction of total assets in [0, 1]}, e.g. {'510300.SS': 0.3, 'GC=F': 0.2}. Symbols must already be tracked (see track_asset). A null value clears that asset's target (back to an equal split). The weights must sum to <= target_allocation_stock (the new one if you pass it in the same call).",
        +  "title": "Target Pcts"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "target_allocation_stock",
        -  "target_allocation_cash"
        -]
    • Addedsubmit_committee
    • Changedtrack_asset6 fields changed
      • addedInput schema / properties / alert_day_drop_pct
        Added value: +{
        +  "anyOf": [
        +    {
        +      "exclusiveMinimum": 0,
        +      "maximum": 100,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alert when the latest daily bar's drop vs the previous close reaches this many percentage points (3 = 3%, not a 0-1 fraction). On a closed market that is the last session; each trading day is reported once.",
        +  "title": "Alert Day Drop Pct"
        +}
      • addedInput schema / properties / alert_day_rise_pct
        Added value: +{
        +  "anyOf": [
        +    {
        +      "exclusiveMinimum": 0,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alert when the latest daily bar's rise vs the previous close reaches this many percentage points (3 = 3%); each trading day is reported once.",
        +  "title": "Alert Day Rise Pct"
        +}
      • addedInput schema / properties / alert_drawdown_from_cost_pct
        Added value: +{
        +  "anyOf": [
        +    {
        +      "exclusiveMinimum": 0,
        +      "maximum": 100,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alert when a held position is this many percentage points below its average cost (10 = 10%). Only evaluated for assets you hold.",
        +  "title": "Alert Drawdown From Cost Pct"
        +}
      • addedInput schema / properties / alert_price_above
        Added value: +{
        +  "anyOf": [
        +    {
        +      "exclusiveMinimum": 0,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alert when the price reaches or exceeds this level. Same price basis as status.current_price (held: cost currency, gold booking = CNY per gram; tracked-only: the quote source's own price).",
        +  "title": "Alert Price Above"
        +}
      • addedInput schema / properties / alert_price_below
        Added value: +{
        +  "anyOf": [
        +    {
        +      "exclusiveMinimum": 0,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Alert when the price falls to or below this level (same price basis as alert_price_above). Must be below alert_price_above if both are set.",
        +  "title": "Alert Price Below"
        +}
      • addedInput schema / properties / target_pct
        Added value: +{
        +  "anyOf": [
        +    {
        +      "maximum": 1,
        +      "minimum": 0,
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Target weight of this asset as a fraction of total assets, in [0, 1] (0.3 = 30%); read by rebalance_plan. The weights of all tracked assets must sum to <= target_allocation_stock, otherwise the write is rejected and the current sum is reported. Assets without one split the remainder equally. To clear a target use set_allocations with a null value.",
        +  "title": "Target Pct"
        +}
    • Changedwithdraw1 field changed
      • addedInput schema / properties / idempotency_key
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Optional client-generated key (e.g. a UUID4). When retrying this SAME call after a timeout or an unknown result, reuse the same key: the ledger records it once and later calls return {\"status\": \"duplicate\"} without touching cash or holdings. Only the key is compared, not the arguments โ€” a different order (other symbol/units/price/amount) needs a new key, or it is silently treated as the retry.",
        +  "title": "Idempotency Key"
        +}
  3. 3 tool updatesv0.42.4
    • Changedbuy4 fields changed
      • addedInput schema / properties / currency / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / currency / default
        Previous value: -"CNY"New value: +null
      • changedInput schema / properties / currency / description
        Previous value: -"Currency of `price`, e.g. 'CNY', 'USD', 'AUD'."New value: +"Currency of `price`, e.g. 'CNY', 'USD', 'AUD'. Omit to use the existing position's currency (CNY for a new position); a different currency than the position's is rejected."
      • removedInput schema / properties / currency / type
        Removed value: -"string"
    • Changedrecord_existing_position4 fields changed
      • addedInput schema / properties / currency / anyOf
        Added value: +[
        +  {
        +    "type": "string"
        +  },
        +  {
        +    "type": "null"
        +  }
        +]
      • changedInput schema / properties / currency / default
        Previous value: -"CNY"New value: +null
      • changedInput schema / properties / currency / description
        Previous value: -"Currency of `price`, e.g. 'CNY', 'USD', 'AUD'."New value: +"Currency of `price`, e.g. 'CNY', 'USD', 'AUD'. Omit to use the existing position's currency (CNY for a new position); a different currency than the position's is rejected."
      • removedInput schema / properties / currency / type
        Removed value: -"string"
    • Changedtrack_asset1 field changed
      • changedInput schema / properties / max_single_invest_cny / description
        Previous value: -"Per-decision investment cap in CNY. Required when creating a new entry; optional on update."New value: +"Per-decision investment cap in CNY. On a new entry, defaults to the strategy-level max_single_invest_cny; optional on update."
  4. 3 tool updatesv0.41.2
    • Changedbuy1 field changed
      • addedInput schema / properties / existing_position
        Added value: +{
        +  "default": false,
        +  "description": "Not supported on buy. For a position held before using openInvest call `record_existing_position`; passing true here returns an error instead of deducting cash.",
        +  "title": "Existing Position",
        +  "type": "boolean"
        +}
    • Changeddecisions4 fields changed
      • addedInput schema / properties / days / minimum
        Added value: +1
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 20,
        +  "description": "Max decisions listed, newest first; 0 = all.",
        +  "minimum": 0,
        +  "title": "Limit",
        +  "type": "integer"
        +}
      • addedInput schema / properties / symbol
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Only this ticker (case-insensitive), e.g. 'GC=F'.",
        +  "title": "Symbol"
        +}
      • addedInput schema / properties / verdict
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Only this verdict, e.g. 'ACCUMULATE', 'HOLD', 'TRIM'.",
        +  "title": "Verdict"
        +}
    • Addedrecord_existing_position
  5. 19 tool updatesv0.34.0
    • Addedadd_news_source
    • Addedbuy
    • Addeddeposit
    • Addeddiscipline
    • Addedexplain_decision
    • Addedhistory
    • Addedingest_event
    • Addedlive_prices
    • Addednews_sources
    • Addedrecord_execution
    • Addedremove_news_source
    • Addedrun_committee
    • Addedsell
    • Addedstatus
    • Addedstrategy
    • Addedtrack_asset
    • Addeduntrack_asset
    • Addedwhat_if
    • Addedwithdraw
  6. 9 tool updatesv0.31.7
    • Removedbuy
    • Removeddiscipline
    • Removedexplain_decision
    • Removedingest_event
    • Removedlive_prices
    • Removedrecord_execution
    • Removedsell
    • Addedset_allocations
    • Removedwhat_if
  7. 5 tool updatesv0.31.6
    • Removedhistory
    • Removedrun_committee
    • Addedsell
    • Removedtrack_asset
    • Removeduntrack_asset
  8. 6 tool updatesv0.31.5
    • Removeddeposit
    • Removedsell
    • Removedset_allocations
    • Removedstatus
    • Removedstrategy
    • Removedwithdraw
  9. 14 tool updatesv0.31.4
    • Changedbuy8 fields changed
      • addedInput schema / properties / currency / description
        Added value: +"Currency of `price`, e.g. 'CNY', 'USD', 'AUD'."
      • addedInput schema / properties / kind / description
        Added value: +"Asset kind tag, e.g. 'equity', 'etf', 'commodity'."
      • addedInput schema / properties / price / description
        Added value: +"Execution price per unit, in `currency`."
      • addedInput schema / properties / price / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / symbol / description
        Added value: +"yfinance ticker, e.g. 'AAPL', '510300.SS', 'GC=F'."
      • addedInput schema / properties / unit_label / description
        Added value: +"Human display label for units (default '่‚ก', i.e. shares)."
      • addedInput schema / properties / units / description
        Added value: +"Quantity bought; must be > 0."
      • addedInput schema / properties / units / exclusiveMinimum
        Added value: +0
    • Changeddecisions1 field changed
      • addedInput schema / properties / days / description
        Added value: +"Look-back window in days."
    • Changeddeposit3 fields changed
      • addedInput schema / properties / amount / description
        Added value: +"Amount to add; must be > 0."
      • addedInput schema / properties / amount / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / currency / description
        Added value: +"ISO-style currency code, e.g. 'CNY', 'USD', 'AUD'."
    • Changedexplain_decision1 field changed
      • addedInput schema / properties / decision_id / description
        Added value: +"\"<date>/<symbol>\", e.g. \"2026-07-03/GC=F\" โ€” exactly as returned by the decisions tool."
    • Changedhistory1 field changed
      • addedInput schema / properties / n / description
        Added value: +"Maximum number of recent trades to return."
    • Changedingest_event6 fields changed
      • addedInput schema / properties / ingested_by / description
        Added value: +"Your own agent identity (e.g. 'hermes') for provenance; distinct from source."
      • addedInput schema / properties / published_at / description
        Added value: +"ISO 8601 publication time, if known."
      • addedInput schema / properties / snippet / description
        Added value: +"Short excerpt or summary of the article body."
      • addedInput schema / properties / source / description
        Added value: +"Publisher name (e.g. 'Reuters') โ€” the news outlet."
      • addedInput schema / properties / title / description
        Added value: +"Headline of the news item."
      • addedInput schema / properties / url / description
        Added value: +"Canonical source URL (also the dedup key)."
    • Changedrecord_execution4 fields changed
      • addedInput schema / properties / decision_id / description
        Added value: +"\"<date>/<symbol>\" from the decisions tool output."
      • addedInput schema / properties / executed / description
        Added value: +"True if the user acted on the verdict, False if they declined."
      • addedInput schema / properties / reason / description
        Added value: +"The user's stated reason (especially when declined)."
      • addedInput schema / properties / trade_ids / description
        Added value: +"Optional trade record IDs to link explicitly."
    • Changedrun_committee4 fields changed
      • addedInput schema / properties / force / description
        Added value: +"Re-run even if a verdict already exists for today."
      • addedInput schema / properties / max_rounds / description
        Added value: +"Cross-challenge debate rounds."
      • addedInput schema / properties / max_rounds / minimum
        Added value: +1
      • addedInput schema / properties / symbol / description
        Added value: +"Any yfinance ticker (US / HK / A-share / ETF / crypto / commodities), e.g. 'AAPL', 'GC=F', '510300.SS'."
    • Changedsell5 fields changed
      • addedInput schema / properties / price / description
        Added value: +"Execution price per unit, in the holding's cost currency."
      • addedInput schema / properties / price / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / symbol / description
        Added value: +"yfinance ticker of an existing holding."
      • addedInput schema / properties / units / description
        Added value: +"Quantity sold; must be > 0."
      • addedInput schema / properties / units / exclusiveMinimum
        Added value: +0
    • Changedset_allocations6 fields changed
      • addedInput schema / properties / target_allocation_cash / description
        Added value: +"Cash weight in [0, 1], e.g. 0.3. Must sum to ~1.0 with stock."
      • addedInput schema / properties / target_allocation_cash / maximum
        Added value: +1
      • addedInput schema / properties / target_allocation_cash / minimum
        Added value: +0
      • addedInput schema / properties / target_allocation_stock / description
        Added value: +"Stock weight in [0, 1], e.g. 0.7. Must sum to ~1.0 with cash."
      • addedInput schema / properties / target_allocation_stock / maximum
        Added value: +1
      • addedInput schema / properties / target_allocation_stock / minimum
        Added value: +0
    • Changedtrack_asset6 fields changed
      • addedInput schema / properties / channel / description
        Added value: +"Where the user actually buys it (broker/app name)."
      • addedInput schema / properties / display_name / description
        Added value: +"Human-friendly name shown in reports."
      • addedInput schema / properties / max_single_invest_cny / description
        Added value: +"Per-decision investment cap in CNY. Required when creating a new entry; optional on update."
      • addedInput schema / properties / price_offset_pct / description
        Added value: +"Systematic offset between quote and actual fill price, in percent (e.g. bank gold spread)."
      • addedInput schema / properties / sell_fee_pct / description
        Added value: +"Sell-side fee in percent, used by fee-aware math."
      • addedInput schema / properties / symbol / description
        Added value: +"yfinance ticker to track, e.g. 'AAPL', '0700.HK', 'BTC-USD'."
    • Changeduntrack_asset1 field changed
      • addedInput schema / properties / symbol / description
        Added value: +"yfinance ticker currently in the tracked list."
    • Changedwhat_if3 fields changed
      • addedInput schema / properties / pct / description
        Added value: +"Hypothetical percent change, e.g. -10 for a 10% drop. Provide exactly one of pct or price."
      • addedInput schema / properties / price / description
        Added value: +"Hypothetical absolute target price (alternative to pct)."
      • addedInput schema / properties / symbol / description
        Added value: +"yfinance ticker held or tracked by the user, e.g. 'NDQ.AX', 'GC=F', '510300.SS'."
    • Changedwithdraw3 fields changed
      • addedInput schema / properties / amount / description
        Added value: +"Amount to remove; must be > 0."
      • addedInput schema / properties / amount / exclusiveMinimum
        Added value: +0
      • addedInput schema / properties / currency / description
        Added value: +"ISO-style currency code, e.g. 'CNY', 'USD', 'AUD'."
  10. 18 tool updatesv0.31.0
    • First observedbuy
    • First observeddecisions
    • First observeddeposit
    • First observeddiscipline
    • First observedexplain_decision
    • First observedhistory
    • First observedingest_event
    • First observedlive_prices
    • First observedrecord_execution
    • First observedrun_committee
    • First observedsell
    • First observedset_allocations
    • First observedstatus
    • First observedstrategy
    • First observedtrack_asset
    • First observeduntrack_asset
    • First observedwhat_if
    • First observedwithdraw

TDQS

A3.9/5.0

Scored across 36 tools

Disambiguation4/5

Most tools target clearly distinct resources or lifecycle steps: ledger cash movements, trade booking, fund-order legs, committee stages, and read-only reporting are well separated. The main ambiguity is between the two committee paths (run_committee vs prepare_committee/submit_committee) and some overlap between track_asset and set_allocations for targets/alerts, but the descriptions generally disambiguate them.

Naming Consistency4/5

The naming is consistently snake_case and mostly follows clear verb_noun conventions such as record_fee, place_fund_order, track_asset, and submit_committee. The deviations are read-only tools named as bare nouns (status, strategy, history, decisions), which is predictable enough but not a strict verb_noun pattern throughout.

Tool Count2/5

The server covers several substantial subsystems โ€” portfolio ledger, fund orders, committee orchestration, news ingestion, reporting, and strategy โ€” but 36 tools is a very large surface for an agent to navigate. While each tool may earn its place in a broad product, the count is heavy and increases selection and context costs.

Completeness4/5

Coverage is strong: cash deposits/withdrawals, buy/sell, fees, dividends, splits, return of capital, existing positions, off-exchange fund order lifecycle, strategy targets, alerts, committee decisions, execution tracking, and news source management are all present. Remaining gaps are minor, such as no general arbitrary-symbol quote lookup and no obvious correction/delete operation for erroneous ledger entries beyond idempotency safeguards.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Personal investment management advisor that exposes tools for accounts, portfolios, trades, market data, strategies, risk control, and advice, enabling AI agents to analyze and provide structured investment recommendations.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Deterministic market-state engine for trading agents โ€” zero LLM in the signal path. 8 tools: structural market state & phase, action gate (GO/WATCH/HOLD), entry/target/invalidation coordinates, bar-by-bar state timeline, composed view cards, and pre-trade intent validation. Every output traces to a bar-stamped ledger with a public daily self-scoring track record.
    3
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Portfolio & trading-strategy stress diagnostics for AI agents: multi-asset stress with hedge-break detection, a daily preregistered regime outlook and deflated-Sharpe backtest-integrity checks. Remote streamable-HTTP endpoint with a free tier (no key); this repo is the public server card.
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    Provides multi-agent equity research for US markets with provenance-backed financial data from SEC EDGAR, technicals, macro, and Alpaca paper trading, enforcing risk limits and journaling theses.
    27
    -