Skip to main content
Glama

KeyVex

Server Details

US public financial disclosures for AI agents: Congress trades, SEC filings, FEC, lobbying, more

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL

TDQS

A4.1/5.0

Scored across 64 tools

Disambiguation4/5

Most tools target clearly distinct datasets (insider filings vs transactions vs holdings, contracts vs grants, 13D/G vs 13F vs N-PORT). A few near-neighbors exist — e.g., get_ofac_sdn vs get_screening_list (overlapping SDN coverage), and the Form 144/insider filing trio — but descriptions explicitly delineate scope and warn which to use when.

Naming Consistency5/5

Nearly universal verb_noun snake_case pattern (get_* across the board), with only one intentional exception (unified_search) that reflects its distinct fan-out behavior. Extremely predictable naming.

Tool Count2/5

64 tools is far beyond the 15-25 sweet spot and well into the range where an agent's tool-selection accuracy degrades. While each tool covers a genuinely distinct government/financial dataset, the breadth (SEC forms, FEC, FARA, OSHA, NLRB, EPA, FEMA, FAA, CFTC, Treasury, NIH, FDA, etc.) makes discovery and disambiguation costly for a single server.

Completeness4/5

Coverage across the financial/regulatory/political-influence domain is remarkably deep — insider filings/transactions/holdings, 13D/13F/N-PORT, contracts/grants, enforcement across eight regulators, lobbying, FARA, FEC, and congressional data. Minor gaps exist (e.g., 13F short positions excluded by design, per-holding N-PORT detail requiring external fetch, Roll-call per-member votes not yet supported), but no obvious workflow dead-ends.

Available Tools

64 tools
get_activist_stakesA
Read-only
Inspect

Returns Schedule 13D / 13G beneficial-ownership disclosures — filings made by anyone holding ≥5% of a class of registered equity securities. Each record is one reporting person on one filing (joint filings emit multiple rows under the same accession_number). Use this when the user asks about: who's accumulating large stakes, activist campaigns, takeover targets, hostile bids, or institutional concentration in a name. Also for 'who owns this company at the 5%+ level?' questions. Two flavors, distinguished by is_activist: - 13D (is_activist=true): filer signals INTENT TO INFLUENCE control. Activist campaigns, takeover stakes, hostile bidders. - 13G (is_activist=false): filer is PASSIVE. Mutual funds, advisers, banks, insurers, qualified institutional holders. Filter is_activist: true to see only the takeover-style filings — much higher signal-to-noise than the 13G firehose, which is dominated by routine quarterly disclosures from Vanguard, BlackRock, etc. COVERAGE FLOOR: KeyVex's ingestion of Schedule 13D/G filings begins January 2024. Filings before 2024 are not in the collection. A 13D/G query for activity in 2023 or earlier returns zero records — this is the collection's coverage boundary, not a per-entity gap. 13D/A and 13G/A AMENDMENT EXIT FILINGS: when a filer reports they have divested below the 5% threshold, the resulting row carries shares_owned: 0 and percent_of_class: 0. These rows are CORRECT — an exit IS zero — not missing data. To distinguish active stakes from exit filings, filter by shares_owned > 0 or by min_percent_of_class. ⚠ THIS TEXT USED TO SAY Item 4 WAS NOT AVAILABLE HERE. It is, as of 2026-08-28. Pass include_filing_narrative:true for the filer's own 'Item 4: Purpose of Transaction' — where board seats, consent rights and control intentions are actually declared — plus Item 2 (the ownership chain behind the filer), Item 2(d)-(e) (criminal and civil proceedings, as prose), Item 3 (source of funds) and Item 6 (the contracts with the issuer that implement Item 4). It is off by default only because it is long, not because it is missing: measured at 58.5% of a row. Rows holding withheld narrative say so via filing_narrative_available. 13D only.

ParametersJSON Schema
NameRequiredDescriptionDefault
cusipNo9-character CUSIP of the security being reported on. Useful for cross-class filings (preferred vs common).
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
tickerNoIssuer stock symbol filter, e.g. 'AAPL'. Case-insensitive.
sort_byNoField used for ordering and for the since/until date filters. Default: filing_date.
filer_cikNoFiler (reporting person) CIK. Exact match.
filer_nameNoFull or partial filer name; case-insensitive substring match. Example: 'BlackRock' matches all BlackRock entities.
sort_orderNoDefault: desc (most recent / largest first).
company_cikNoIssuer SEC CIK (10-digit, padded with leading zeros). Alternative to ticker.
filing_typeNoExact filing type. /A variants are amendments. Original 13D/G filings (no /A) signal a fresh crossing of the 5% threshold.
is_activistNoFilter to 13D filings only (true) or 13G only (false). Omit to include both. Use is_activist=true to surface takeover/activist signal.
min_percent_of_classNoFilter to filings where percent_of_class >= this value. Use to focus on large/concentrated stakes.
include_filing_narrativeNoInclude the Schedule 13D narrative items in each row: Item 2 (the reporting person and the ownership chain behind them), Item 2(d)-(e) (criminal convictions and civil securities proceedings in the last five years, as PROSE — usually a denial, never reduced to a flag), Item 3 (source of funds: own money vs borrowings), Item 4 (PURPOSE OF TRANSACTION — the filer's own statement of intent, where board seats, consent rights and control ambitions are declared) and Item 6 (the contracts with the issuer that implement Item 4). Default FALSE because these are long: measured at 58.5% of a row and ~548 KB on a 50-row page, and the same text repeats once per reporting person on a filing. Ask for it when researching WHY a stake was taken; leave it off when you want the numbers. Rows that have narrative available but withheld carry `filing_narrative_available: true`, so an absent field is never mistaken for a filer who said nothing. 13D only — 13G filings carry no narrative items.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover only the safe-read profile; the description carries everything else. It discloses the January 2024 ingestion floor and that pre-2024 queries return zero by boundary rather than entity gap, explains that 13D/A exit rows with shares_owned:0 are correct rather than missing data, and warns that include_filing_narrative adds ~58.5% to each row / ~548 KB per 50-row page. That is exactly the kind of behavior an agent cannot infer from structured fields.

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 definition, then bolded subsections for 13D vs 13G, coverage floor, exit filings and the narrative flag, so a skimmer hits the decision-relevant facts first. It is long and the 'THIS TEXT USED TO SAY Item 4 WAS NOT AVAILABLE' passage is meta-commentary that costs space, but almost 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 14-parameter, no-output-schema research tool, the description supplies the domain frame (13D/13G semantics), the coverage boundary, the zero-value edge case, and the optional-heavy-field tradeoff — everything an agent needs to call it correctly and interpret empty or zero results. Nothing material is left to inference.

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 real meaning: is_activist is framed as the 13D-intent vs 13G-passive distinction, include_filing_narrative is explained item-by-item (Item 2/2(d)-(e)/3/4/6) with its cost and its 13D-only limitation, and min_percent_of_class is offered as the way to separate live stakes from exit rows. It stops short of adding syntax 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+resource ('Returns Schedule 13D / 13G beneficial-ownership disclosures'), defines the record grain (one reporting person per filing, joint filings emit multiple rows), and pins the 5% threshold that makes the data meaningful. An agent can distinguish this from get_institutional_holdings, get_insider_filings and get_proxy_filings 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?

Explicit when-to-use list ('who's accumulating large stakes, activist campaigns, takeover targets, hostile bids, institutional concentration'), plus the exact user phrasing it answers. It also names the internal alternative — filter is_activist:true for signal vs the 13G 'firehose' of routine Vanguard/BlackRock quarterly filings — which is a genuine routing decision.

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

get_aircraft_registryA
Read-only
Inspect

Returns FAA aircraft registrations — the releasable registry of ~314K currently US-registered aircraft, one record per N-number: the aircraft (manufacturer, model, seats, engines, weight class, year built, engine type), and the REGISTRANT — name, type (Individual / Corporation / LLC / Government / Co-Owned, the FAA's own legend, with the verbatim code), address, and up to five co-owner names. Use this when the user asks: who owns an aircraft (by N-number), what aircraft a company / person / nonprofit registers, corporate-jet fleets, aircraft registered in a state, or to join tail numbers seen in flight-tracking data to owners. Lookups: n_number is a direct hit ('N123AB' or '123AB'). registrant_name matches the primary registrant AND co-owner names. Note: many corporate jets register through trustee banks (e.g. 'BANK OF UTAH TRUSTEE') or aircraft-management LLCs — an absent company name is NOT proof the company has no aircraft. Registry posture: a CURRENT-roster snapshot refreshed monthly from the FAA's daily-updated file. snapshot_date is the last snapshot a record appeared in — stale means since deregistered. Deregistered- aircraft history (the FAA DEREG file) is a planned follow-up. Pure-publisher posture: FAA records as published, parsed by KeyVex; type labels are the FAA's own documentation legends, never our inference.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records. Default 50, max 500.
stateNoTwo-letter registrant state (e.g., 'TX').
sort_byNoDefault last_action_date (most recent registry activity first).
n_numberNoDirect lookup by registration (with or without the N prefix).
sort_orderNoDefault desc.
manufacturerNoCase-insensitive substring against the manufacturer (e.g., 'gulfstream', 'cessna').
registrant_nameNoCase-insensitive substring against registrant + co-owner names.
aircraft_type_codeNoFAA code: 4 fixed-wing single-engine, 5 fixed-wing multi-engine, 6 rotorcraft, 1 glider, 2 balloon, 9 gyroplane, H hybrid lift, O other.
registrant_type_codeNoFAA code: 1 Individual, 2 Partnership, 3 Corporation, 4 Co-Owned, 5 Government, 7 LLC, 8 Non-Citizen Corp, 9 Non-Citizen Co-Owned.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/non-destructive. The description adds substantial behavioral context the annotations cannot: it is a CURRENT-roster monthly snapshot of a daily-updated FAA file, snapshot_date staleness implies deregistration, deregistered history is a planned (not yet available) follow-up, and results are FAA records republished verbatim rather than inferred. These disclosures directly shape how an agent should interpret and caveat results.

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?

Content is front-loaded: what it returns first, then use cases, then lookup semantics, then caveats. Most sentences earn their place given nine parameters and no output schema. It is somewhat over-long and includes mildly editorial framing ('Pure-publisher posture ... parsed by KeyVex'), plus a stray hyphen in 'Deregistered- aircraft', but nothing that obstructs use.

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 no output schema, the description carries the full return-value burden and does so: it enumerates the aircraft and registrant fields, the five-co-owner cap, the FAA type-code legend, and the snapshot/staleness semantics. Combined with 100% parameter coverage and read-only annotations, an agent has everything needed to call and interpret this tool.

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 the baseline is 3 and the schema already documents all nine parameters (including n_number's N-prefix tolerance and registrant_name's co-owner matching). The description reinforces those semantics and adds interpretive nuance for registrant_name — that a missing company match does not disprove ownership — which meaningfully aids filter choice.

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 names a specific verb+resource ('Returns FAA aircraft registrations') and quantifies scope (~314K US-registered aircraft, one record per N-number). It further enumerates exactly what a record contains (aircraft attributes and registrant details), so the agent knows precisely what it is getting and can distinguish it from any sibling in this large tool set.

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 an explicit enumeration of triggering user intents: 'who owns an aircraft (by N-number), what aircraft a company / person / nonprofit registers, corporate-jet fleets, aircraft registered in a state, or to join tail numbers seen in flight-tracking data to owners.' It also supplies a crucial when-interpreting caveat (trustee-bank and management-LLC registrations mean an absent company name is not proof of no ownership). No sibling overlaps, so no alternative needs naming.

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

get_alertsAInspect

Your watchlist alerts, newest first — events matched to the tickers, members of Congress and federal-contract recipients (UEIs) on YOUR watchlist, for the API key making the call. Kinds: congress_trade — a congressional trade disclosed this week in a ticker or by a member on your watchlist. initial_13d — an initial Schedule 13D (a new 5%+ activist stake) filed this week in a ticker on your watchlist. federal_contract — federal awards at or above your threshold that KeyVex first reported this week, new or newly modified (a later modification of an award you were already alerted to does not alert again). An event alerts only when its own date (disclosure, filing, the award's latest modification) is within 7 days of detection and not before you added the entry, so a watchlist never replays history. Each alert's data is the source record as KeyVex stored it when the alert fired, with KeyVex's internal _ fields removed; the matching tool may present the same record differently. Paginate with next_cursor. The watchlist itself is managed on keyvex.com. Webhooks (pro and up): each POST carries X-KeyVex-Timestamp and X-KeyVex-Signature = sha256 HMAC of '.' with your secret. Receivers MUST verify the signature and REJECT a timestamp older than 5 minutes (replay protection); redirects are never followed; answer 2xx within 5 s.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoOnly this kind.
limitNoPage size (default 50).
sinceNoOnly alerts detected at or after this ISO date or date-time.
cursorNonext_cursor from the previous page.

TDQS

A4.6/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden and does so: it discloses dedup behavior ('a later modification of an award you were already alerted to does not alert again'), the no-history-replay rule, that each alert's data has KeyVex internal `_` fields stripped, pagination via next_cursor, and the full webhook contract (HMAC signature over '<timestamp>.<raw body>', 5-minute replay window, no redirects, 5s 2xx deadline).

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 first sentence front-loads the core identity and the kind list follows immediately, with eligibility and webhook rules after. It is dense but nearly every clause carries operational meaning; the webhook paragraph is the only slightly tangential block for a read/polling tool.

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?

Despite having no output schema, the description explains the shape of the returned `data` (the source record as stored, internal fields removed) and the pagination token, and it clarifies authentication scope (the API key determines whose watchlist) and where the watchlist is managed. 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%, so the baseline is 3, but the prose goes beyond it: it enumerates and defines each enum value for `kind` (congress_trade, initial_13d, federal_contract) and confirms cursor usage ('Paginate with next_cursor'). The semantics of `since` and `limit` are left to 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 ('Your watchlist alerts, newest first') and scopes it precisely to events matched against the tickers, members and UEIs on YOUR watchlist for the calling API key. It distinguishes itself from raw-data siblings by noting 'the matching tool may present the same record differently,' so an agent knows this is the alert feed, not get_congressional_trades or get_federal_contracts.

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?

Explains what each of the three kinds means and states the eligibility condition (event date within 7 days of detection and not before the entry was added), which tells the agent exactly when results appear. It implies the raw-source alternatives ('the matching tool may present the same record differently') but never explicitly says when to prefer those over this feed, so it falls short of full when/when-not routing.

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

get_annual_financial_disclosuresA
Read-only
Inspect

Returns Form 278 (Public Financial Disclosure / Annual Financial Disclosure) filings — the annual snapshot members of Congress file each year showing assets, income sources, liabilities, transactions, gifts, outside positions, and (for spouse + dependent children) the same. The same filings are published free as news at https://keyvex.com/disclosures under 5 U.S.C. § 13107(c). SCOPE — v1 covers BOTH chambers: Senate (Senate eFD) and House (House Clerk). Filed by every senator and representative (and senior executive-branch officials, federal judges) by May 15 each year. Use this when the user asks about: a member's asset composition, outside income sources, board seats / outside positions, liabilities (mortgages, loans), or for news reporting on annual disclosures. CONTENT — when a filing's schedules were machine-parsed, content_parsed is true and the record carries structured assets (Schedule A) and liabilities arrays plus asset_count / liability_count. value_range / amount_range are the disclosed RANGES (e.g., '$50,001 - $100,000'), NOT point estimates — KeyVex does not collapse a range to a single number. SENATE rows carry the ranges verbatim. HOUSE rows are read from the House Clerk PDF by column position. On a House candidate or new-filer report, whose income prints in two columns ('current year to filing', 'preceding year'), income_range is empty — neither is the reporting period; report_url shows both. A row KeyVex could not read with confidence carries parse_unreliable: true, and for such rows report_url is authoritative. Net-worth roll-up is intentionally NOT provided (it would be a KeyVex-derived aggregate, not a disclosed value). When schedules are unavailable — Senate PAPER (scanned-image) filings, which carry no machine-readable text, or the occasional parse skip — content_parsed is false and coverage_note names the limitation; follow report_url to read the original. This honest coverage boundary is never a silent omission. Different from get_congressional_trades: PTRs are per-trade real-time notices (filed within 30-45 days), while Form 278 is the year-end balance-sheet snapshot. Combine both for the full activity + position view of a member. Report types: 'Annual' (yearly filing covering prior calendar year), 'New Filer' (initial disclosure on entering office), 'Termination' (final disclosure on leaving office), 'Combined' (annual+termination for filer who left mid-year), 'Amendment' (correction of a prior filing), 'Other' (rare).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax records to return (1-500). Default 50.
partyNoExact match on the record's party, where the party is the party the member held on the date of the record (a trade's transaction date, a disclosure's filing date); for a date outside the member's terms in office, the party of their nearest term (the last one before that date, or the first one after it). So party='Democrat' matches filings made while the filer was a Democrat. Empty on filings by candidates who never served.
sinceNoISO date (YYYY-MM-DD). Lower bound on the chosen sort_by field. Defaults to filtering by filing_date.
stateNoTwo-letter state code (e.g., 'CA', 'TX'). Exact match. Empty for candidate filings (the Senate eFD covers candidates too).
untilNoISO date (YYYY-MM-DD). Upper bound on the chosen sort_by field.
chamberNoFilter to one chamber ('senate' or 'house'). v1 covers both.
sort_byNoField to sort by. Default 'filing_date' (most recent filings first).
sort_orderNoSort direction. Default 'desc'.
bioguide_idNoFiler's bioguide_id (e.g., 'P000197' for Nancy Pelosi). Exact match. Most precise filter. A filing carries a bioguide_id only when exactly one member of Congress can be its filer: reports by candidates who never served carry none, and neither does a filing saved before its filer appeared in the member catalog. So for a brand-new member, cross-check with member_name.
filing_yearNoThe year of the FILING period being reported on (NOT the date filed). Most filers report the prior calendar year — e.g., a May 2026 Annual filing has filing_year=2025. New Filer reports cover the partial year up to filing.
member_nameNoSubstring match against the filer's full name (case-insensitive). E.g., 'Pelosi', 'Mitch McConnell'. Use bioguide_id when possible for precision.
report_typeNoFilter to one filing flavor. Default is unfiltered (returns all types).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the read-only, non-destructive, open-world profile, and the description adds substantial behavior beyond that: content_parsed/coverage_note flags, parse_unreliable rows with report_url as authoritative, House vs Senate parsing differences, income_range empty cases, and the deliberate omission of net-worth roll-ups. This is exactly the added context the dimension rewards.

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 purpose, then organized into SCOPE, CONTENT, USE-this-when, and DIFFERENT-from blocks, so a long description is justified by the 12-parameter surface. A few sentences (the 'honest coverage boundary is never a silent omission' framing) lean rhetorical rather than informative, keeping it short of a 5.

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, no-output-schema, open-world disclosure tool, the description covers chambers, filing cadence, report types, parse reliability, data provenance, and the intentional coverage boundaries. Nothing an agent needs to call it correctly or interpret results 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%, so the baseline is 3, but the description adds real meaning beyond the schema: it defines each report_type flavor ('Annual' covers prior calendar year, 'New Filer' initial disclosure, etc.) that the schema only labels as 'one filing flavor', and clarifies the range-vs-point-estimate semantics of value_range/amount_range. It does not add syntax detail for the remaining filters.

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 (returns Form 278 annual financial disclosure filings), enumerates the content (assets, income sources, liabilities, transactions, gifts, outside positions) and explicitly differentiates from the sibling get_congressional_trades with a clear PTR-vs-year-end-snapshot contrast. An agent can identify this tool 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?

Provides an explicit 'Use this when the user asks about...' list (asset composition, outside income, board seats, liabilities, news reporting) plus a named alternative and a combine-both recommendation for the full activity+position view. Both when-to-use and the sibling relationship are spelled out.

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

get_bank_financialsA
Read-only
Inspect

Returns quarterly financials for every FDIC-insured US bank — FDIC BankFind Suite (RIS) data derived from Call Reports, one record per (bank, quarter-end) from 1984 to the present. Covers ~4,400 active institutions per modern quarter, most of which never file with the SEC — this is the banking-sector complement to get_fundamentals. Use this when the user asks about: a specific bank's assets / deposits / profitability / capital ratios, bank league tables ('largest banks in Texas'), deposit flight or brokered-deposit reliance, nonperforming-asset trends, or to pair bank fundamentals with OCC/FDIC/Fed enforcement actions and CFPB complaints. Record shape: identity (cert = FDIC certificate number, the stable bank key; name/city/state), balance sheet in $ THOUSANDS (total_assets, total_deposits, equity_capital, net_loans_leases, securities, loan buckets, brokered_deposits, insured-deposit estimates), income statement in $ thousands (net_income, interest income/expense, noninterest income/expense, provisions), and FDIC-computed ratios in percent (roa, roe, net_interest_margin, efficiency_ratio, leverage_ratio, tier1_risk_based_ratio, cet1_ratio, total_risk_based_ratio, nonperforming_assets_ratio, net_chargeoffs_ratio, loans_to_core_deposits). CONVENTIONS (Call Report): income-statement items are YEAR-TO-DATE (Q3 net_income = nine months, not the quarter alone; Q4 = full year); ratios are FDIC's annualized computations; roe_quarterly is the single-quarter ROE. Balance-sheet items are point-in-time. Matching a bank: cert (FDIC certificate #) is exact and stable — resolve it once via a name substring query, then use cert for history. Banks are subsidiaries: 'JPMorgan Chase Bank, National Association' (cert 628) is the insured bank, not the NYSE-listed holding company — for the parent's SEC financials use get_fundamentals. League tables: report_date='' + sort_by='total_assets' (e.g., report_date '2026-03-31'). Quarter-ends are 03-31 / 06-30 / 09-30 / 12-31. Latest quarter fills in progressively for ~60 days after quarter end as banks file. Pure-publisher: FDIC's numbers as published, no derived health scores.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect lookup: '{cert}-{YYYY-MM-DD}' (e.g., '3511-2026-03-31'). Fastest path.
certNoFDIC certificate number (exact) — the stable bank identifier (e.g., 3511 = Wells Fargo Bank NA, 628 = JPMorgan Chase Bank NA).
nameNoCase-insensitive substring against the institution name (e.g., 'silicon valley', 'first republic').
limitNoMaximum records to return. Default 50, max 500.
sinceNoreport_date lower bound (YYYY-MM-DD inclusive).
stateNoTwo-letter state code (exact, e.g., 'CA', 'TX').
untilNoreport_date upper bound (YYYY-MM-DD inclusive).
sort_byNoDefault report_date. total_assets requires an exact report_date filter (league-table mode).
sort_orderNoDefault: desc.
report_dateNoExact quarter-end (YYYY-MM-DD: 03-31 / 06-30 / 09-30 / 12-31). Combine with sort_by='total_assets' for league tables.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/destructive/openWorld, and the description adds substantial context beyond them: Call Report provenance, ~4,400 institutions and 1984-present coverage, the YTD income-statement convention, FDIC-annualized ratios, the ~60-day progressive fill for the latest quarter, and the 'pure-publisher, no derived health scores' caveat.

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 purpose and is well-organized under labeled sections (CONVENTIONS, Matching a bank, League tables), with each section carrying usable content. It is dense and long, but almost every sentence earns its place; minor trimming would still be possible.

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?

No output schema exists, and the description fully covers the return shape (identity, balance sheet in $ thousands, income statement, FDIC ratios) plus conventions and key-resolution guidance. An agent has 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.

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 real workflow meaning: cert is the exact stable key to resolve once via a name substring, the report_date + sort_by='total_assets' league-table recipe, and valid quarter-end formats. It does not add syntax beyond the schema, so it stops short of 5.

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 ('Returns quarterly financials for every FDIC-insured US bank') with scope and provenance, and explicitly distinguishes itself from the sibling get_fundamentals as 'the banking-sector complement.' An agent can identify the tool 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 Guidelines5/5

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

Provides an explicit when-to-use list (assets/deposits/profitability/capital ratios, league tables, deposit flight, NPA trends, pairing with enforcement/complaints) and names the alternative (get_fundamentals) plus the condition that selects it (parent holding company SEC financials).

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

get_billsA
Read-only
Inspect

Returns congressional bill metadata from api.congress.gov. Use this when the user asks about: bills introduced this Congress, the status of a specific bill, House vs Senate bill volume, what bills mention a topic, or to bridge from a roll-call vote (legislation_type + legislation_number) to the underlying bill. Source: api.congress.gov v3 (Library of Congress). Covers ALL bill types: HR (House Bill), S (Senate Bill), HRES (House Simple Resolution), SRES (Senate Simple Resolution), HJRES (House Joint Resolution), SJRES (Senate Joint Resolution), HCONRES (House Concurrent Resolution), SCONRES (Senate Concurrent Resolution). v1A returns metadata only: title, type + number, originating chamber, latest action (date + text), and links. Sponsors, cosponsors, full action history, bill text, and CRS summaries live at api_url (structured JSON) and congress_gov_url (public HTML). Agents follow those for prose detail. Bill identifiers are stable composite keys formatted as {congress}-{TYPE}-{number}, e.g., '119-HR-134', '119-S-1234', '118-HJRES-5'. Use bill_id for the fastest direct lookup. Pure-publisher posture: KeyVex returns what's in the public record. No legislative outcome predictions, no 'likely to pass' signals.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum bills to return. Default 50, max 500.
sinceNoLatest-action date lower bound (ISO YYYY-MM-DD inclusive). Useful for 'what's moved recently'. NOTE: this filters the most-recent floor/committee action, which can move with activity even on a bill introduced a year ago. For 'introduced in the last N months' questions, use introduced_since instead.
titleNoCase-insensitive substring against bill title. Useful for topic searches ('artificial intelligence', 'border security', etc.).
untilNoLatest-action date upper bound (ISO YYYY-MM-DD inclusive).
bill_idNoComposite bill identifier ('{congress}-{TYPE}-{number}', e.g., '119-HR-134'). Direct doc lookup, fastest path.
sort_byNoSort key. Default: latest_action_date (most recently active first). Use introduction_date to sort by when the bill was originally introduced.
congressNoCongress number (e.g., 119 = January 2025 onward; 118 = January 2023 - January 2025).
bill_typeNoType code. HR/S are bills; HRES/SRES are simple resolutions (single-chamber, non-binding); HJRES/SJRES are joint resolutions (both chambers, can become law); HCONRES/SCONRES are concurrent resolutions (both chambers, non-binding).
sort_orderNoDefault: desc.
origin_chamberNoFilter to bills originating in one chamber.
introduced_sinceNoIntroduction-date lower bound (ISO YYYY-MM-DD inclusive). The right filter for 'bills introduced in the last N months' — distinct from since/until, which track latest action. Older bill records may have an empty introduction_date if they were ingested before that field was added; those will be excluded from introduced_since/introduced_until results until the bill is re-scraped.
introduced_untilNoIntroduction-date upper bound (ISO YYYY-MM-DD inclusive).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/non-destructive, and the description goes well beyond by disclosing exactly what v1A returns (metadata only) versus what is deliberately not included (sponsors, cosponsors, action history, text, CRS summaries), plus the 'pure-publisher, no predictions' posture. This is rich behavioral context not present in structured fields.

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 usage before details, and every section serves a purpose. It is lengthy and the full bill-type enumeration partially duplicates the bill_type enum already documented in the schema, which is mild redundancy, but overall it is well organized and skimmable.

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 no output schema, the description carries the full burden of describing returns and does so explicitly (title, type+number, originating chamber, latest action, links) and redirects to api_url/congress_gov_url for detail. Nothing an agent needs to call this 12-param, all-optional tool 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%, so the baseline is 3, but the description adds genuine meaning beyond the schema: the composite {congress}-{TYPE}-{number} key format, that bill_id is the fastest direct-lookup path, and the semantic distinction between latest-action filters and introduction-date filters. It reinforces rather than merely repeats 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+resource (returns congressional bill metadata) plus scope (all bill types, from api.congress.gov). It explicitly distinguishes itself from siblings by naming the roll-call-vote bridge use case and pointing prose detail to other sources, so an agent can tell what it does versus get_roll_call_votes or unified_search.

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-to-use list mapped to concrete user questions (bills this Congress, status of a specific bill, House vs Senate volume, topic mentions, roll-call bridge). It also names the fastest path (use bill_id) and disambiguates since/until vs introduced_since in the schema. Alternatives and exclusions are covered.

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

get_cftc_cot_reportsA
Read-only
Inspect

Returns CFTC Commitments of Traders (COT) report rows — weekly aggregated futures + options-on-futures positioning by trader class. The COT report is the macro positioning dataset for U.S. futures markets. Released every Friday 3:30 PM ET for the prior Tuesday close. Trader classes (legacy futures-only report): - Non-commercial (large speculators — hedge funds, CTAs) - Commercial (hedgers — producers, swap dealers) - Non-reportable (small speculators) Killer query patterns: - Macro positioning snapshot this week: latest_only=true (gives the latest report row for every contract in one query) - Large-spec extremes in S&P: commodity_name='S&P 500 STOCK INDEX' + sort_by='noncomm_net' + sort_order='desc' - Gold positioning history: commodity_name='GOLD' + since='2026-01-01' - Currency COT: contract_market_name substring 'YEN' / 'EURO' Source: publicreporting.cftc.gov/resource/jun7-fc8e.json (Socrata API, free, unauthenticated). Covers EVERY regulated U.S. futures + options- on-futures contract — agricultural commodities, metals, energy, financials, FX, crypto. Pure-publisher posture: raw positioning numbers, no derived sentiment scores. Key derived fields (computed from raw): noncomm_net (large-spec net), comm_net (hedger net), nonrept_net (small-spec net). Concentration fields show top-4 / top-8 trader net long/short concentration.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect doc lookup ({contract_code}-{YYYY-MM-DD}). Fastest path.
limitNoMax records. Default 50, max 500.
sinceNoInclusive lower bound on report_date (YYYY-MM-DD).
untilNoInclusive upper bound on report_date (YYYY-MM-DD).
sort_byNoSort key. Default: report_date.
sort_orderNoDefault: desc.
latest_onlyNoWhen true, returns only the most recent report row per contract (one row per contract instead of weekly history).
commodity_nameNoExact commodity name from CFTC's catalog (e.g., 'S&P 500 STOCK INDEX', 'GOLD', 'CRUDE OIL', 'EURO FX').
contract_market_nameNoCase-insensitive substring on contract_market_name (e.g., 'S&P 500', 'GOLD', 'CRUDE OIL', 'JAPANESE YEN'). Client-side filter.
cftc_contract_market_codeNoExact CFTC contract code (e.g., '13874A' = E-mini S&P 500, '088691' = Gold, '067651' = Crude Oil WTI).

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=true, destructiveHint=false), and the description adds real context beyond them: Friday 3:30 PM ET release cadence for the prior Tuesday close, the public Socrata endpoint, free/unauthenticated access, and the 'pure-publisher posture' with no derived sentiment scores. It stops short of pagination or rate-limit behavior, so a 4 rather than 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 is front-loaded in the first sentence, followed by release timing, trader classes, query patterns and provenance in a logical order. It is long and the trader-class/query-pattern blocks are somewhat list-heavy, but nearly every sentence carries decision-relevant information, so only mild trimming is warranted.

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 10 parameters, no required params, and no output schema, the description does the heavy lifting well: it explains the dataset, coverage, freshness, and the derived fields an agent will see in results. It omits pagination/return-shape details and the meaning of the concentration fields beyond a brief mention, leaving minor 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?

Schema coverage is 100%, so the baseline is 3, but the description adds value the schema does not: it demonstrates how parameters combine (latest_only semantics, sort_by='noncomm_net' with sort_order='desc', commodity_name='GOLD' + since=) and names the derived fields (noncomm_net, comm_net, nonrept_net) that back the sort enum. That is meaningful enrichment over the structured fields.

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 ('Returns CFTC Commitments of Traders (COT) report rows') and immediately defines the payload: weekly aggregated futures + options-on-futures positioning by trader class. No sibling tool covers COT data, so an agent can place this unambiguously.

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 'Killer query patterns' section gives concrete, goal-oriented parameter recipes (latest_only=true for a weekly snapshot, commodity_name + sort_by='noncomm_net' for large-spec extremes, since= for history). It does not name a when-not-to-use condition or an alternative tool, which keeps it short of a 5, but the usage context is clear and actionable.

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

get_company_profileA
Read-only
Inspect

Returns ONE company's reference profile: legal name, CIK, tickers + exchanges, SIC industry classification, state of incorporation, HQ and mailing addresses, phone, fiscal year end, EIN, former names, a plain-English business summary (condensed from the latest 10-K Item 1), CEO + board of directors (from the latest DEF 14A proxy), federal- contract activity summary (USAspending join, with a ready-to-run get_federal_contracts query), company logo reference, and — on paid plans — the latest end-of-day closing price (price_eod; Close Prices from Tiingo.com). For price HISTORY use get_daily_prices. The price_iex_last / price_tngolast intraday fields remain unlicensed stubs. ⚠ ASSEMBLED REFERENCE DATA — unlike KeyVex's mirror datasets, this profile is NOT byte-faithful government mirroring. Fields are assembled from multiple bases and each carries its own provenance envelope: source, source_type (mirrored | derived | self_collected | asserted | licensed), fetched_at, as_of, and per-field meta (e.g. the SEC accession number every derived field traces to). A field that cannot be established is UNKNOWN with a machine-readable reason; a field staler than its declared cadence reads as INSUFFICIENT_DATA (value retained for knowing consumption). Factual data only — no ratings, rankings, scores, or opinions. Leadership staleness note: CEO/board come from the latest annual proxy and can lag mid-year changes; meta.leadership_change_events_since_proxy lists any 8-K Item 5.02 (officer/director change) filings made after the proxy — follow up with get_material_events for the detail. Lookup is by ticker OR cik (exactly one required). Ticker matches the company's current EDGAR-listed tickers; renamed/delisted tickers miss — use the CIK. An ambiguous ticker (multiple CIKs) returns an error naming the candidate CIKs rather than guessing.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoSEC CIK, padded or not ('320193' or '0000320193'). Exactly one of ticker/cik.
tickerNoCompany ticker, e.g. 'AAPL', 'BRK-B' (EDGAR hyphen convention for class shares). Exactly one of ticker/cik.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations cover only the read-only safety profile, and the description adds substantial behavioral context beyond them: per-field provenance envelopes (source_type, fetched_at, as_of), UNKNOWN/INSUFFICIENT_DATA staleness semantics, paid-plan gating for price_eod, unlicensed stub fields, and the assembled-not-mirrored caveat. This is exactly the kind of disclosure the annotations cannot 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 field enumeration is front-loaded and the key constraints are stated early, but the description is very long and dense, with some detail (Tiingo attribution, the price_iex_last stub note) that adds bulk relative to decision value. It is informative but not tightly trimmed.

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?

There is no output schema, so the description carries the full burden of describing return values, and it does so thoroughly — enumerating fields, provenance, staleness handling, and error behavior. An agent has 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.

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; the description adds real value beyond the schema by specifying that ticker matches only current EDGAR-listed tickers (renamed/delisted miss, use CIK) and that ambiguous tickers return a named-candidate error. It also notes the hyphen convention for class shares.

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 ('Returns ONE company's reference profile') and enumerates the exact fields returned, so an agent knows precisely what it gets. It explicitly distinguishes itself from siblings like get_daily_prices (price history) and get_federal_contracts (contract detail).

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 lookup rules ('exactly one of ticker/cik'), names the failure modes (renamed/delisted tickers miss, ambiguous ticker errors with candidate CIKs), and routes follow-ups to get_daily_prices and get_material_events. 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.

get_congressional_tradesA
Read-only
Inspect

Returns trade records disclosed by U.S. members of Congress under the STOCK Act — Senate eFD and House Clerk Periodic Transaction Reports (PTRs). Each record is one disclosed transaction by a member or their immediate family. The same filings are published free as news at https://keyvex.com/disclosures under 5 U.S.C. § 13107(c). Use this when the user asks about: who in Congress traded a specific stock, what trades a specific member made, recent congressional trading activity, or filings within a date range. Important: This data is disclosed trades, with reporting lag up to 45 days. The disclosure_date is when the public could first see the trade; the transaction_date is when the trade actually happened. For 'what did Congress just disclose buying' questions, sort by disclosure_date. For 'what did Congress hold around a specific market event', filter by transaction_date. Each amount is a range like '$1,001 - $15,000' (Senate filers report ranges, not exact amounts). The amount_min and amount_max fields parse those bounds for filtering. STOCK Act allows reporting in 11 standard ranges from $1,001 up to over $50,000,000. Each record's party is the party the member held on the date of the record (a trade's transaction date, a disclosure's filing date); for a date outside the member's terms in office, the party of their nearest term (the last one before that date, or the first one after it).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
ownerNoWho owns the asset. STOCK Act covers spouse and dependent children's trades too — this filter narrows to one ownership category.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
cursorNoPass the `next_cursor` from the previous response VERBATIM to fetch the next page. Keep every other filter and the sort identical while paging. Omit to start from the top.
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive. Leave empty to query across all tickers.
chamberNoFilter to one chamber. Senate PTRs are HTML-parsed from efdsearch.senate.gov. House PTRs are PDF-parsed from disclosures-clerk.house.gov.
sort_byNoField used by since/until and ordering. Default: disclosure_date (when the public first saw the trade).
min_amountNoFilter to trades with amount_min >= this value (USD). Use to focus on larger disclosed trades. Note: amount ranges are minimums, so '$1,001 - $15,000' has amount_min=1001.
sort_orderNoDefault: desc (most recent first).
bioguide_idNoMember's permanent congressional ID, e.g. 'C001035' for Susan Collins. Preferred over member_name when known. Pair with get_member_profile to enrich a trade with the member's party/state/committee assignments.
member_nameNoFull or partial member name; case-insensitive substring match. Examples: 'Collins', 'Pelosi'.
amendment_statusNoFilter by whether the row came from an original filing or an AMENDMENT. Default: all three, deliberately — most amendment rows are NOT duplicates, they are disclosures the amendment added (181 of 198 recent Senate amendment rows have no original). Use 'original' to exclude restatements, accepting that you will also drop genuinely new disclosures. 'unknown' is every House row: the Clerk index carries no amendment indicator, so it cannot be determined from the source.
transaction_typeNoFilter by disclosed transaction type. 'buy' = Purchase (P); 'sell' = Sale, full or partial (S); 'exchange' = Exchange (E) — bond maturities, corporate spin-offs, and share-class exchanges, which are disclosed trades too. Leave empty to include all three.
exclude_supersededNoDrop ORIGINAL disclosures that a later amendment restates. Default FALSE — they are returned, marked `superseded_by_amendment: true`, and the envelope carries `superseded_rows_included` plus a coverage_warning naming the count. ⚠ SET THIS WHENEVER YOU ARE SUMMING AMOUNTS. A member who amends a report has BOTH versions in the data — Boozman's Chevron trade appears as an amendment and an original, identical in every visible field under two report ids — so any total over the default response DOUBLE-COUNTS them. 2,360 of 13,642 original Senate rows are in that state (measured 2026-08-27). It is not the default because Senate amendments do not declare WHICH report they replace, so the match is made on member + transaction date + ticker + owner + asset name; dropping on that identity alone is a judgement the caller should make knowingly. House rows are never affected — the Clerk index carries no amendment indicator, so their status is 'unknown' and they are never marked.
include_non_open_marketNoPhase A v0.52.0 (2026-05-24): controls whether NON-MARKET events appear in the result. When false (honest default for direction queries), keeps ONLY OPEN_MARKET rows plus INSUFFICIENT_DATA rows (passthrough — unclassified is not the same as confirmed non-market, never silently dropped). Excludes both NON_OPEN_MARKET_TRANSFER (charitable contributions, gifts, donations detected in `comment`) AND EQUITY_COMP (rare for congressional but handled identically for parity). Honest-by-default: with transaction_type='buy'|'sell' → defaults to FALSE so a charitable contribution can't pollute a sell-total query. Without transaction_type → defaults to TRUE (everything tagged honestly). The transaction_type field on each row is NEVER mutated. Example: `member_name:'Pelosi', transaction_type:'sell'` by default EXCLUDES Pelosi's Trinity University contribution; `include_non_open_market:true` re-includes it. Envelope carries `unclassifiable_records_retained: N` when any INSUFFICIENT_DATA rows passed through.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only declare read-only/open-world/non-destructive; the description goes well beyond by disclosing the up-to-45-day reporting lag, the disclosure_date vs transaction_date distinction, that amounts are ranges not exact values (11 standard STOCK Act brackets), and how party is attributed for dates outside a member's terms. These are material interpretation caveats an agent cannot get from the 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?

Front-loads what the tool returns, then usage, then the 'Important' caveats block — a sound ordering with no redundancy against the schema. It loses a point for the promotional sentence ('published free as news at https://keyvex.com/disclosures'), which does nothing to help an agent select or invoke the tool.

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 16-parameter, no-output-schema tool, the description supplies the domain model an agent needs (lag, date semantics, ranges, amendment/supersession implications at a high level). The response envelope fields (superseded_rows_included, coverage_warning, unclassifiable_records_retained) are only explained in schema text, so return-shape expectations are not fully covered here.

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 the baseline is 3, but the description adds genuine query-level meaning: which date field to sort/filter on for which question, how amount ranges map to amount_min/amount_max for filtering, and what owner/party values actually represent. It does not touch the heaviest parameters (exclude_superseded, include_non_open_market), which remain schema-only.

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 ('Returns trade records disclosed by U.S. members of Congress under the STOCK Act') and pins the exact sources (Senate eFD and House Clerk PTRs), plus the granularity ('each record is one disclosed transaction by a member or their immediate family'). An agent can distinguish this from get_insider_transactions or get_annual_financial_disclosures on the entity 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?

Gives explicit triggering questions ('who in Congress traded a specific stock', 'what trades a specific member made', 'recent congressional trading activity', 'filings within a date range') and even routes between sort_by choices for two question shapes. It does not name alternatives or state when NOT to use it (e.g., use get_member_profile for enrichment, which is only mentioned in the schema), 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.

get_consumer_complaintsA
Read-only
Inspect

Returns consumer complaints filed with the Consumer Financial Protection Bureau (CFPB). Each record is one filing against a bank, credit reporting agency, mortgage servicer, debt collector, fintech, or crypto firm — with company response status, timeliness flag, and (when consented) consumer narrative. Use this when the user asks about: complaint volume against a specific company, top issues at a credit reporting agency, regional complaint patterns, untimely responses by a financial institution, or as a leading indicator of upcoming CFPB/OCC/FDIC enforcement action. COVERAGE — live passthrough (source:'live'): each call queries CFPB's own search API over the FULL 15.7M+ complaint database, full history, current as of CFPB's publication. The response's total_count is CFPB's authoritative count for your filtered query — USE IT for volume answers (the results array is just the requested page). total_count is omitted when an issue or sub_product filter is active (those apply after the upstream query, so the upstream total wouldn't match). If CFPB is unreachable the tool falls back to a small cached sample (source:'cache' + coverage_warning) — do NOT infer volume in that mode. Note: company matching is word-based against the company name ('experian', 'wells fargo'), not arbitrary-substring. Product taxonomy (the top categories): - 'Credit reporting or other personal consumer reports' — Equifax, Experian, TransUnion. ~80% of recent complaint volume. - 'Debt collection' - 'Mortgage' - 'Credit card or prepaid card' - 'Checking or savings account' - 'Payday loan, title loan, or personal loan' - 'Money transfer, virtual currency, or money service' - 'Vehicle loan or lease' - 'Student loan' Company-response values: 'Closed with explanation', 'Closed with non-monetary relief', 'Closed with monetary relief', 'In progress', 'Untimely response', 'Closed without relief'. Cross-source tip: pair with get_enforcement_actions(source:'cftc'|'occ'| 'fdic'|'sec'|'doj', text:'') to see if complaint volume preceded a formal enforcement action.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect lookup by CFPB complaint_id.
issueNoCase-insensitive substring against the issue field (e.g., 'incorrect information', 'fraud', 'debt is not yours').
limitNoDefault 50, max 500.
sinceNoISO date (YYYY-MM-DD). Applied to sort_by field.
stateNoTwo-letter state code (e.g., 'CA', 'NY'). Case-insensitive.
untilNoISO date (YYYY-MM-DD).
companyNoCase-insensitive substring against company name (e.g., 'experian', 'jpmorgan', 'capital one').
productNoExact product match (e.g., 'Mortgage', 'Debt collection', 'Credit reporting or other personal consumer reports').
sort_byNoDefault date_received.
sort_orderNoDefault desc.
sub_productNoExact sub-product match.
submitted_viaNoChannel filter.
timely_responseNoFilter to complaints with timely company response (within CFPB's 15-day window) or not.

TDQS

A4.6/5.0
Behavior4/5

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

With readOnlyHint/openWorldHint already covering the safety profile, the description goes further: it explains the live-vs-cache fallback, the presence of a coverage_warning, that volume must not be inferred in cache mode, and that total_count is authoritative but omitted when issue/sub_product filters are active. These are non-obvious operational traits that materially affect interpretation. It stops short of covering pagination mechanics or rate limits.

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 front-loaded: purpose first, then usage, then coverage/behavioral caveats. The taxonomy and company-response value lists are long but genuinely useful for constructing valid filters; a couple of enumerations could be tightened without loss.

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 13 optional params, no output schema, and open-world behavior, the description compensates fully — it explains the return surface (total_count vs results, source, coverage_warning), filter interactions, and fallback semantics. An agent has everything needed to call and interpret it correctly.

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 baseline is 3, but the description adds real meaning: it enumerates the exact product taxonomy values and clarifies that company matching is word-based rather than arbitrary-substring. It also warns that issue/sub_product are applied post-upstream (changing what total_count means), which the schema does not convey.

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 specific verb+resource ('Returns consumer complaints filed with the CFPB') and defines the record granularity ('Each record is one filing against a bank, credit reporting agency...'). It names the concrete fields returned (company response status, timeliness flag, narrative), which clearly separates it from siblings like get_enforcement_actions.

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 enumerates explicit use cases ('complaint volume against a specific company, top issues at a credit reporting agency, regional complaint patterns, untimely responses...'), including forward-looking use as an enforcement indicator. It also names an alternative and the condition to pair with it (get_enforcement_actions with source-specific params), which is exactly the when/when-with guidance the dimension rewards.

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

get_corporate_patentsA
Read-only
Inspect

Returns US patent applications from the USPTO Open Data Portal, keyed on the APPLICANT (the corporate owner). Each record is one application's front-page metadata: title, applicant(s), first inventor + inventor count, filing/effective dates, status, entity size, application type. Follow source_url (USPTO Patent Center) for the full file wrapper / documents. Use this when the user asks: what is a company patenting, how many patents did a company file (and when), recent patents in a company's portfolio, or to cross-reference R&D output against insider/congressional activity, contracts, or fundamentals for the same company. company_name is the corporate APPLICANT and matches case-insensitively, but patents are filed under an IP-HOLDING ENTITY, not the household brand. Use the full legal applicant string for best recall — e.g. 'Google LLC', 'Microsoft Technology Licensing, LLC', 'Amazon Technologies, Inc.', 'QUALCOMM Incorporated', 'International Business Machines Corporation', 'Meta Platforms, Inc.', 'NVIDIA Corporation', 'Lockheed Martin Corporation', 'The Boeing Company', 'Apple Inc.', 'Intel Corporation', 'Tesla, Inc.'. COVERAGE — live-first (source:'live'): when company_name is set, each call queries USPTO live over the full ~12.9M-application index (the whole filing history of that applicant, most-recent first), with since/until on filing_date applied at the source. On USPTO outage the tool falls back to a cached recent slice for a dozen tracked big filers (source:'cache' + coverage_warning) — don't infer totals there. With NO company_name it serves that same recent cache (browse). application_number is a direct lookup.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 200.
sinceNoISO date (YYYY-MM-DD). Only applications with filing_date on or after this date.
untilNoISO date (YYYY-MM-DD). Only applications with filing_date on or before this date.
sort_orderNoOrder by filing_date. Default: desc (most-recent first).
company_nameNoCorporate applicant (IP-holding entity), case-insensitive. Triggers a LIVE USPTO query over that applicant's full history. Use the full legal entity, e.g. 'Microsoft Technology Licensing, LLC' (not 'Microsoft'), 'Google LLC' (not 'Google').
application_numberNoExact USPTO application number for a direct lookup (cache). Example: '17/123456'.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only cover readOnly/openWorld/destructive, but the description adds substantial operational behavior beyond them: live-first querying over a ~12.9M-application index, since/until applied at the source, fallback to a cached recent slice on outage with source:'cache' + coverage_warning and the warning not to infer totals, and browse behavior with no company_name. This is exactly the kind of context annotations cannot 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?

Front-loaded and logically ordered (returns → usage → caveat → coverage), but over-long for the content; the list of eleven example applicant strings is excessive and the coverage paragraph is dense. Several sentences restate schema content, so not every 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?

No output schema exists, so the description must cover return semantics, and it does: record shape, source_url follow-up, live/cache coverage semantics, and the applicant-naming pitfall. For a 6-param, complex, open-world tool this is complete enough to call correctly.

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 baseline is 3, but the description adds real meaning: the critical caveat that patents are filed under an IP-holding entity rather than the household brand (with 11 concrete legal-string examples), case-insensitive matching, and the live-vs-cache behavior tied to company_name. Some of this duplicates the schema descriptions, so it is above baseline but not fully additive.

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: returns US patent applications from the USPTO Open Data Portal, keyed on the corporate APPLICANT. It enumerates exactly what each record contains (title, applicants, inventor count, dates, status, entity size) and names the follow-up source (source_url at USPTO Patent Center), so an agent knows precisely what it gets. No sibling tool covers patents, so differentiation is inherent.

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, concrete usage contexts ('what is a company patenting', 'how many patents did a company file', cross-referencing R&D against insider/congressional activity, contracts, fundamentals). This maps user intent to the tool clearly, though it never states when NOT to use it or names an alternative sibling.

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

get_crowdfunding_offeringsA
Read-only
Inspect

Returns SEC Form C filings — Regulation Crowdfunding offerings, 2016-05→present: startup raises on Wefunder / StartEngine / Republic and other funding portals. One record per filing with the issuer (legal form, jurisdiction, incorporation date, website), the PORTAL (name + CIK + CRD), offering terms (security type — SAFEs appear as 'Other' with the description, price, target and maximum amounts, deadline, oversubscription), and the issuer's own DISCLOSED FINANCIALS (total assets, cash, revenue, net income, debt — current + prior fiscal year, dollars) plus employee count. Use this when the user asks about: startup crowdfunding activity, what a company raised on a portal, portal market share, early-stage issuers in a state, or revenue/assets of a crowdfunding company. filing_type maps the form family: 'offering' (C, C/A) | 'progress_update' (C-U) | 'annual_report' (C-AR — re-discloses financials yearly) | 'termination' (C-TR). is_withdrawal covers the -W variants. One issuer CIK typically has a chain: C → C-U → C-AR… — filter cik + sort asc to read it. Financial fields are null where a variant omits them. Reg A+ (Form 1-A 'mini-IPOs') is a different form family — planned as its own dataset; Reg D private placements are in get_private_placements. Pure-publisher posture: issuer-reported numbers as filed, parsed by KeyVex — Form C financials are self-reported and generally unaudited (reviewed at most); treat them accordingly.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoIssuer CIK (any zero-padding).
limitNoMaximum filings. Default 50, max 500.
sinceNoFiling date lower bound (YYYY-MM-DD inclusive).
untilNoFiling date upper bound (YYYY-MM-DD inclusive).
sort_orderNoSort by filing date. Default desc.
filing_typeNoForm-family filter (see description).
issuer_nameNoCase-insensitive substring against issuer (or SPV co-issuer) name.
portal_nameNoCase-insensitive substring against the funding portal (e.g. 'wefunder', 'startengine').
jurisdictionNoIssuer's state/country of organization (two-letter, e.g. 'DE').
accession_numberNoDirect lookup by EDGAR accession number.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already establish read-only, non-destructive, open-world behavior. The description goes well beyond them: it discloses the pure-publisher posture, that financials are issuer-reported and generally unaudited, that fields are null where a variant omits them, and the C → C-U → C-AR chain structure — genuinely useful context an agent needs to interpret results.

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?

Dense but well front-loaded: what it returns first, then usage, then enum mapping, then exclusions and caveats. Every sentence carries information, though the block is long enough that a tighter edit is conceivable.

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 no output schema, the description carries the full burden and does so — it enumerates the returned fields (issuer, portal, offering terms, financials, employee count) and flags the caveats that affect interpretation. Nothing material is missing for correct invocation.

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. The description adds real value beyond the schema: it maps filing_type enum values to form families, explains the cik + sort asc pattern for reading filing chains, and notes null-semantics for financial fields. Minor gap: it references is_withdrawal, which is not an exposed 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 the specific resource (SEC Form C filings / Reg CF offerings), the covered period (2016-05→present), and the exact record shape. It explicitly names and excludes sibling form families (Reg A+ via get_reg_a_offerings, Reg D via get_private_placements), so an agent can disambiguate 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 Guidelines5/5

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

Gives an explicit 'Use this when the user asks about:' list of concrete intents (portal market share, early-stage issuers in a state, revenue/assets of a crowdfunding company) and routes alternative form families to named sibling tools. Both when-to-use and when-not-to-use are present.

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

get_daily_pricesA
Read-only
Inspect

Returns daily end-of-day closing-price history for one US-listed ticker (stocks, ETFs, mutual funds — including delisted tickers, so historical analysis is survivorship-bias-free). Coverage extends back as far as 1962 for the oldest names, subject to plan history limits. PAID PLANS ONLY. Each row: date, close (as-traded), adj_close (split+dividend adjusted — use THIS for charts and return calculations), div_cash (dividend with that ex-date), split_factor (e.g. 4 = 4:1 split that session). include_ohlc=true adds the session's open / high / low / volume and their adjusted variants — the day's RANGE, which is what a stop or a target is actually tested against. On weekly/monthly these are aggregated over the period (first open, highest high, lowest low, summed volume), not the last session's values. Omit the flag and the response is unchanged. The full requested window returns in ONE call — no pagination. For multi-year ranges prefer frequency='weekly' or 'monthly' (last bar per period; dividends summed, split factors compounded) to keep responses compact: 10 years daily ≈ 2,500 rows vs ~120 monthly. One call = one ticker. Compare securities with multiple calls. Close Prices from Tiingo.com.

ParametersJSON Schema
NameRequiredDescriptionDefault
sinceNoISO date YYYY-MM-DD inclusive. Default: earliest your plan allows.
untilNoISO date YYYY-MM-DD inclusive. Default: latest available.
tickerYesTicker symbol, e.g. 'AAPL', 'SPY', 'BRK-B' (hyphen for share classes).
frequencyNoDownsampling. Default daily. Use weekly/monthly for multi-year charts.
include_ohlcNoAdd open/high/low/volume (+ adjusted variants) to each row. Default false. Aggregated per period on weekly/monthly.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already flag readOnly/openWorld/non-destructive, and the description layers on genuinely useful behavior: paid-plan gating, no pagination (full window in one call), survivorship-bias-free coverage back to 1962, weekly/monthly aggregation semantics (first open, highest high, lowest low, summed volume), and the Tiingo data source.

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 purpose and scope, and each sentence carries information an agent needs (coverage, plan gating, row schema, flag behavior, pagination). Dense but not padded; slightly long, so not a clean 5.

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 read tool with no output schema, the description effectively documents the returned row fields and their adjusted variants, coverage limits, and aggregation behavior, leaving nothing material an agent would need before calling it.

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 baseline is 3. The description goes further, explaining what adj_close is for ('use THIS for charts and return calculations'), that div_cash is tied to the ex-date, and how include_ohlc aggregates on weekly/monthly—interpretation the schema alone doesn't convey.

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 ('returns daily end-of-day closing-price history for one US-listed ticker') plus the instrument scope (stocks, ETFs, mutual funds, delisted names). This cleanly separates it from intraday quote, fundamentals, and holdings siblings without ambiguity.

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 when-to-use guidance: prefer frequency='weekly'/'monthly' for multi-year ranges, and 'one call = one ticker, compare with multiple calls.' It states the PAID PLANS ONLY prerequisite. It stops short of naming specific sibling tools to prefer over this one (e.g. intraday vs daily), so 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.

get_delistingsA
Read-only
Inspect

Returns SEC delisting and deregistration filings: the Form 25 family (notification of removal from listing on a national exchange under Rule 12d2-2) and the Form 15 family (certification terminating or suspending a security class's registration — the 'going dark' filing that ends SEC reporting; 15F variants are the foreign-private-issuer equivalents). Use this when the user asks: was/is a company being delisted, which companies went dark recently, what securities did an exchange remove, or to pair with tender offers / 8-Ks / insider sales around an exit event. Reading a record: action='delisting' (25 family) vs 'deregistration' (15 family) is a faithful form→rule mapping, not an opinion. 25-NSE is filed BY THE EXCHANGE against the issuer (exchange_name/exchange_cik are set) — typically the involuntary path; a bare Form 25 is filed by the issuer itself (voluntary withdrawal, e.g. after a merger). rule_provision carries the cited Rule 12d2-2 provision verbatim — the provision distinguishes the grounds for removal; agents can read the cited paragraph. A merger close typically produces a Form 25 AND a Form 15 within weeks. EDGAR coverage: Form 15 family 1994→present; issuer-filed Form 25 from mid-2001; exchange-filed 25-NSE from 2005 Q4 (the Rule 12d2-2 amendments moved exchange filings onto EDGAR — earlier removals were paper-filed and are not in EDGAR). security_class / rule_provision / exchange fields are populated from the structured 25-NSE XML; 15-family records are metadata-level — follow filing_index_url for the document. Pure-publisher posture: EDGAR records as published.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoIssuer SEC CIK (any zero-padding).
formNoVerbatim form type. 25-NSE = exchange-filed removal; 25 = issuer-filed; 15-12B/15-12G/15-15D = deregistration by registration section; 15F-* = foreign private issuers; /A = amendment.
limitNoMaximum records to return. Default 50, max 500.
sinceNoFiling date lower bound (YYYY-MM-DD inclusive).
untilNoFiling date upper bound (YYYY-MM-DD inclusive).
actionNoForm family: 'delisting' = Form 25 family (exchange removal); 'deregistration' = Form 15 family (going dark).
tickerNoExact ticker (resolved from CIK; '' for unlisted filers).
sort_orderNoSort by filing date. Default desc (newest first).
company_nameNoCase-insensitive substring against the issuer name.
accession_numberNoDirect lookup by EDGAR accession number (e.g., '0000876661-26-000593').

TDQS

A4.6/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnlyHint, openWorldHint, destructiveHint), and the description goes well beyond them: EDGAR coverage windows by form family (15 from 1994, issuer 25 from mid-2001, 25-NSE from 2005 Q4), which fields are XML-populated vs metadata-level, and the 'pure-publisher posture' read-only guarantee.

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 opening sentence is front-loaded with the core purpose and the subsequent dense passages on coverage windows and field provenance earn their place for a 10-parameter tool. It is long and could be broken into clearer sections, but there is little redundant filler.

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 no output schema, the description still explains the return surface (structured 25-NSE XML fields, 15-family records are metadata-level, follow filing_index_url for the document) and the historical coverage limits. An agent has everything needed to call and interpret the results correctly.

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 real interpretive meaning: action='delisting' vs 'deregistration' is a faithful form-to-rule mapping, 25-NSE is filed by the exchange (exchange_name/exchange_cik set) while a bare 25 is issuer-filed, and rule_provision carries the cited provision verbatim.

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 names the specific resource (SEC delisting/deregistration filings) and distinguishes the Form 25 family from the Form 15 family, including the Rule 12d2-2 basis and the 15F foreign-issuer variant. An agent can tell exactly what this tool returns and how it differs from other SEC-filing siblings 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?

It enumerates concrete user intents ('was/is a company being delisted', 'which companies went dark recently', 'what securities did an exchange remove') and suggests pairing with tender offers/8-Ks/insider sales around an exit event. This is clear context, but it never names a competing tool as an explicit alternative nor states 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.

get_drug_adverse_eventsA
Read-only
Inspect

Returns FDA FAERS drug adverse-event reports — every adverse-event / medication-error report submitted to FDA (~20M, 2004→present, growing ~2M/yr). LIVE passthrough to openFDA: results reflect FDA's current data and total_count is openFDA's authoritative count for the filtered query (the results array is just the requested page). Use this when the user asks about: safety signals on a drug, adverse events by reaction type, death/hospitalization outcome counts for a product, a manufacturer's adverse-event footprint, or to pair a safety-signal trend with recalls, approvals, or insider activity. count_by returns TOP TERMS + COUNTS instead of records (e.g. count_by:'reaction' with drug:'ozempic' → the most-reported reactions for that drug) — the right first move for 'what are the side effects of X' questions; follow with a record query for detail. Records are openFDA's fields verbatim: deeply nested (patient.drug[] with openFDA annotations, patient.reaction[]), 5-15KB each — keep limit small. Matching: drug matches brand name, generic name, or the verbatim reported product as a PHRASE ('ozempic', 'semaglutide'); reaction is a MedDRA term phrase ('myocardial infarction'); serious=true filters to reports with a serious outcome; outcome picks one specific flag (death, hospitalization, …). since/until window on receivedate (when FDA received the report). CRITICAL honesty note (FDA's own): FAERS reports are UNVERIFIED and establish NEITHER causation NOR incidence — anyone can report, duplicates exist, reporting is stimulated by publicity, and there is no denominator (prescriptions dispensed). Counts are a reporting signal, not a risk measure. Surface this caveat when presenting counts. Pure-publisher posture: FDA's records as published, parsed by KeyVex — no derived safety scores.

ParametersJSON Schema
NameRequiredDescriptionDefault
drugNoDrug name phrase — brand ('ozempic'), generic ('semaglutide'), or reported product name.
skipNoPagination offset (openFDA hard cap 25,000). Not used in count_by mode.
limitNoRecords per page (default 10, max 100 — records are heavy). In count_by mode: facet rows (default 25, max 1000).
sinceNoFDA receive-date lower bound (YYYY-MM-DD inclusive).
untilNoFDA receive-date upper bound (YYYY-MM-DD inclusive).
countryNoCountry where the event occurred (ISO-2, e.g. 'US').
outcomeNoOne specific seriousness outcome flag.
seriousNotrue = serious reports only (death, hospitalization, disability, …); false = non-serious only.
count_byNoFacet mode: return top terms + counts instead of records (reaction | drug | brand | manufacturer | country).
reactionNoMedDRA reaction term phrase (e.g., 'pancreatitis', 'myocardial infarction').
manufacturerNoManufacturer name phrase (openFDA annotation, e.g. 'novo nordisk').

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint, openWorldHint, destructiveHint=false), yet the description adds substantial context: a LIVE passthrough, the fact that total_count is authoritative while the results array is only the requested page, that records are 5-15KB and limit should stay small, and FDA's own caveat that reports are unverified with no denominator. This is genuinely additive beyond structured data.

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 what the tool returns and well-organized into matching/filter/caveat blocks. It is dense and long (~250 words) with mild repetition in the honesty note, but nearly every sentence earns its place for an 11-param, output-schema-less tool.

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 no output schema, the description carries the return-value burden and does so: records are openFDA fields verbatim, deeply nested (patient.drug[], patient.reaction[]), 5-15KB, while count_by returns top terms plus counts and total_count is the authoritative filtered count. Nothing an agent needs to call and interpret it is missing.

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?

Schema coverage is already 100% (baseline 3), but the description exceeds it with matching semantics not in the schema: drug matches brand/generic/verbatim product as a PHRASE, reaction is a MedDRA phrase, serious vs. outcome are distinguished, since/until window on receivedate, and a concrete count_by example. It meaningfully deepens parameter understanding.

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 ('Returns FDA FAERS drug adverse-event reports') with scope (~20M reports, 2004→present, live passthrough to openFDA). It explicitly distinguishes itself from adjacent tools by describing its role alongside recalls, approvals, and insider activity, so an agent can place it among the ~65 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 an explicit 'Use this when the user asks about' list (safety signals, reactions, outcome counts, manufacturer footprint) and goes further with a decision rule: count_by is 'the right first move' for side-effect questions, followed by a record query for detail. This is exactly the when/when-not/alternatives guidance the dimension asks for.

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

get_economic_indicatorsA
Read-only
Inspect

Returns observations of key US macro, energy, and fiscal indicators from four sources: - BLS (Bureau of Labor Statistics): the canonical labor + price statistics. ~20-series watchlist covering unemployment, payrolls, wages, CPI, PPI, productivity. Most monthly, ECI/productivity quarterly. - FRED (Federal Reserve Economic Data, St Louis Fed): rates, money supply, GDP, PCE inflation, mortgage rates, jobless claims, Fed balance sheet, breakeven inflation, dollar index, consumer sentiment. ~30-series watchlist. Some daily (rates, dollar), weekly (mortgage, Fed assets, jobless claims), monthly, quarterly. - EIA (Energy Information Administration): WTI + Brent crude oil spot prices, Henry Hub natural gas, US gasoline retail price, US crude oil production. Unique energy data not in BLS or FRED. Mostly weekly cadence. - FiscalData (Treasury Bureau of the Fiscal Service): total public debt outstanding TO THE PENNY, daily, 1993→present (split into debt held by the public vs intragovernmental); Monthly Treasury Statement gross receipts / outlays / deficit-or-surplus; average interest rate actually paid on each Treasury security class (Bills/Notes/Bonds/TIPS/FRN + nonmarketable, 2001→present). Filter to one source via source: 'bls' | 'fred' | 'eia' | 'fiscaldata'. Default returns all four unified — series_id disambiguates across catalogs. Use this when the user asks about: unemployment rate, jobs report, nonfarm payrolls, CPI / PCE / inflation, Fed Funds rate, Treasury yields, mortgage rates, yield-curve inversion, money supply / M2, Fed balance sheet / QE / QT activity, GDP, housing starts, retail sales, consumer sentiment, jobless claims, trade balance, dollar strength, national debt / debt ceiling levels, monthly federal deficit, interest cost on the debt, or general macro context for cross-source analysis. Categories (for filtering): - rates — Fed Funds, Treasury yields, mortgage, corporate bonds - gdp — Real + nominal GDP, GDP growth rate - activity — Industrial production, housing starts, retail sales - inflation — CPI/PPI (BLS) + PCE/Core PCE/breakevens (FRED) - employment — Unemployment rates (U-3, U-6), payrolls, jobless claims - labor-force — Labor force participation rate - wages — Average hourly earnings, employment cost index - hours — Average weekly hours - productivity — Nonfarm productivity, unit labor costs - money — M2, Fed total assets, overnight reverse repo - debt — Federal debt (FRED quarterly + FiscalData daily to-the-penny), Treasury general account - fiscal — MTS monthly receipts, outlays, deficit/surplus (positive = deficit, negative = surplus, per Treasury's sign convention) - trade — Trade balance, trade-weighted dollar index - sentiment — U Michigan Consumer Sentiment - energy — WTI/Brent crude, Henry Hub natural gas, retail gasoline, US crude production (EIA) Period format is fixed-width per cadence so lexicographic sort = chronological: - 2026M04 (April 2026), 2026Q01 (Q1 2026), 2026A01 (annual 2026), 2026W18 (week 18 of 2026), 2026D258 (day-of-year 258). Set latest_only=true to get one record per series (the most-recent observation) — useful for 'where are things now' snapshot questions. Daily series under latest_only return only the latest day per series (deduped client-side); without it you can pull arbitrary history. Pure-publisher posture: the unit on each series is documented in the unit field; we do not compute year-over-year deltas, seasonally adjust differently, or derive 'real' vs 'nominal' versions — agents do those calculations on top.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoDefault 50, max 500.
sourceNoFilter to one source. Omit to query all four. BLS = canonical labor + price stats. FRED = rates, money, GDP, PCE inflation, sentiment. EIA = energy prices + production. FiscalData = Treasury debt to the penny, MTS budget totals, avg interest rates on the debt.
sort_byNoDefault period (chronological).
categoryNoBucket filter.
series_idNoExact series ID. BLS examples: 'LNS14000000' (U-3), 'CES0000000001' (payrolls), 'CUUR0000SA0' (CPI). FRED examples: 'DFF' (Fed Funds), 'DGS10' (10Y Treasury), 'PCEPILFE' (Core PCE), 'M2SL' (M2), 'WALCL' (Fed assets), 'UMCSENT' (sentiment). FiscalData examples: 'FISCAL-DEBT-TOTAL-DAILY' (daily national debt), 'FISCAL-MTS-DEFICIT-MONTHLY' (monthly deficit/surplus).
since_yearNoCalendar-year lower bound (inclusive).
sort_orderNoDefault desc.
until_yearNoCalendar-year upper bound (inclusive).
latest_onlyNoWhen true, return only the most-recent observation per series. Useful for 'current state' snapshots.
period_typeNoCadence filter.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations cover only the safety profile (readOnlyHint, openWorldHint, destructiveHint), and the description adds substantial behavior beyond that: the 'pure-publisher posture' disclaimer that no YoY deltas or alternate seasonal adjustments are computed, the fact that units live in a `unit` field, the client-side dedup of daily series under latest_only, and the fiscal sign convention (positive = deficit). This is exactly the extra context annotations cannot carry.

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 purpose and then organized into scannable bullets (sources, trigger phrases, categories, period format, latest_only, posture), so an agent can find what it needs quickly. It is still long, and the per-source bullets partially restate the `source` enum description in the schema, which is mild redundancy rather than waste.

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 no output schema, the description carries the full burden and does so: it explains what a record contains (series, unit field, period), the period encoding, sign conventions, and that raw values are unmodified so agents compute derived metrics themselves. For a 10-parameter, zero-required cross-source tool, nothing essential to correct invocation 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 description coverage is 100%, so the baseline is 3; the description goes further by explaining the fixed-width period format (2026M04, 2026Q01, 2026W18, 2026D258) so lexicographic sort equals chronological, describing what each `source` value contains, mapping the `category` buckets to concrete series, and clarifying the `latest_only` snapshot behavior. That materially enriches semantics the schema alone only gestures at.

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 states a specific verb+resource (returns observations of key US macro, energy, and fiscal indicators) and immediately names the four publisher sources. It is easily separable from siblings like get_daily_prices, get_fundamentals, or get_treasury_auctions because it scopes itself to macro indicator series across BLS/FRED/EIA/FiscalData.

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 an extensive explicit trigger list ('Use this when the user asks about: unemployment rate, jobs report, CPI / PCE, Fed Funds rate, national debt...') plus a category taxonomy for filtering, which gives an agent strong positive routing signals. It never states when NOT to use it or names a sibling alternative for overlapping cases (e.g., Treasury auction or price data), so it falls short of full when/when-not guidance.

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

get_enforcement_actionsA
Read-only
Inspect

Returns SEC + DOJ + CFTC + OCC + FDIC + FTC + Federal Reserve + FinCEN enforcement-related actions. Eight regulators, one tool. Use this when the user asks about: recent SEC charges, DOJ indictments, CFTC derivatives/swaps enforcement, OCC national-bank examination actions, FDIC bank-failure announcements or insured-deposit transfers, FTC antitrust / consumer-protection cases, Federal Reserve actions against banks and individual bankers, FinCEN anti-money-laundering (BSA) penalties, insider trading prosecutions, FCPA actions, fraud cases, or to add a 'negative event' flag to a ticker or person by cross-checking against insider trades, activist filings, or tender offers. Sources: source='sec' — SEC press releases (sec.gov/news/pressreleases.rss). Rolling ~50-item RSS window; refreshes daily. SEC enforcement and policy statements are mixed in the same feed — filter by title substring (e.g., 'charges', 'fraud', 'insider trading') to narrow. source='doj' — DOJ press releases (justice.gov/api/v1/press_releases.json). Latest ~200 records refreshed daily; rich metadata including agency_component (issuing division) and topics[]. Common components: 'Criminal Division', 'Antitrust Division', 'Tax Division', 'Civil Division', 'Office of Public Affairs', 'United States Attorneys'. source='cftc' — CFTC press releases (cftc.gov/PressRoom/PressReleases). HTML index scrape (no RSS). Rolling ~50-item window. Covers derivatives/swaps enforcement, prediction-market jurisdiction, spoofing prosecutions, and policy actions. v1A index-only (no body extracted) — follow url for the substantive announcement. source='occ' — OCC news releases (occ.treas.gov/news-issuances/ news-releases//...). Covers national-bank enforcement, examination findings, capital/leverage rules, interagency announcements. Yearly index. Both OCC-only (nr-occ-...) and interagency (nr-ia-...) releases included; bulletins filtered out. source='fdic' — FDIC press releases (fdic.gov/news/press-releases). Covers bank failures + insured-deposit transfers, exam-result releases, deposit-insurance rule changes, CRA evaluations. Bank-failure announcements are some of the highest-signal FDIC items for agents. source='ftc' — FTC press releases (ftc.gov RSS). Antitrust, merger reviews, deceptive-practices and consumer-protection enforcement. Rolling recent window. source='fed' — Federal Reserve enforcement actions (full history from the Board's enforcement-actions CSV). One record per action per party: cease-and-desist orders, civil money penalties, prohibitions from banking, written agreements — against BOTH banking organizations and individual bankers. topics[] holds the action type(s); agency_component holds the bank (or the individual's affiliated bank); terminated_date is set once the Fed terminates the action (absent = still open). source='fincen'—FinCEN enforcement actions (fincen.gov, complete history). Rare, high-profile anti-money-laundering / Bank Secrecy Act penalties (e.g., TD Bank, Paxful, Brink's). topics[] holds the institution category; release_number holds the matter number; url points at the consent-order PDF. v1A scope: metadata + teaser + description (capped ~3000 chars; empty for CFTC v1A). Full prose lives at url — agents follow for the substantive announcement. Pure-publisher posture: no derived 'severity' or 'outcome prediction' signals. Identifier format: action_id is 'sec-{guid-or-slug}', 'doj-{uuid}', 'cftc-{release-number}', 'occ-{slug}', 'fdic-{slug}', 'ftc-{slug}', 'fed-{date}-{party}-{action}', or 'fincen-{matter-number}'. Stable across re-scrapes. Cross-source tip: pair with get_insider_transactions to detect insider trades by executives at companies later named in enforcement charges, or with get_activist_stakes to spot enforcement-driven exit attempts.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoCase-insensitive substring against title + teaser + description combined. Use for company-name / person-name searches.
limitNoMaximum actions to return. Default 50, max 500.
sinceNoPublished date lower bound (YYYY-MM-DD inclusive).
titleNoCase-insensitive substring against the title / headline (e.g., 'insider trading', 'fraud', 'antitrust').
topicNoFilter by DOJ topic tag (array-contains, e.g., 'Financial Fraud', 'Cybercrime', 'Public Corruption').
untilNoPublished date upper bound (YYYY-MM-DD inclusive).
sourceNoFilter to one issuing agency: sec (SEC), doj (DOJ), cftc (CFTC), occ (OCC bank-regulator), fdic (FDIC bank-regulator), ftc (FTC antitrust + consumer protection), fed (Federal Reserve bank + individual-banker actions), fincen (FinCEN anti-money-laundering penalties).
action_idNoDirect lookup ('sec-{guid}', 'doj-{uuid}', or 'cftc-{release-number}'). Fastest path.
sort_orderNoDefault: desc (most recent announcements first).
agency_componentNoSubstring against the issuing DOJ component (e.g., 'criminal division', 'fraud section', 'antitrust'). Empty for most SEC items.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/destructive=false; the description goes well beyond by disclosing per-source freshness and window behavior (SEC rolling ~50-item RSS, DOJ latest ~200, CFTC HTML scrape with no body extracted), the v1A truncation cap (~3000 chars, empty for CFTC), stable identifier formats per source, and Fed terminated_date semantics. It also states the 'pure-publisher posture: no derived severity or outcome prediction', which prevents an agent from expecting scoring signals.

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 purpose, then trigger scenarios, then a scannable per-source block with aligned labels, ending with cross-source tips — a sensible structure for an 8-source aggregator. It is long (~450 words) and the source list is effectively restated three times (trigger list, source definitions, schema enum), which costs it a point, but nearly every sentence carries non-redundant operational 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?

With no output schema and 10 optional parameters, the description carries the full burden and does: it describes returned field semantics (topics[], agency_component, release_number, terminated_date, url pointing at the consent-order PDF), the v1A teaser-vs-full-prose split, and action_id composition per source. An agent has everything needed to call and interpret results correctly.

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 real meaning beyond the enum documentation: it explains that OCC bulletins are filtered out while OCC-only and interagency releases are included, that titles are mixed SEC enforcement/policy items requiring substring narrowing, and that agency_component is empty for most SEC items. That is substantive per-parameter context the schema alone does not convey.

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 and resource — 'Returns SEC + DOJ + CFTC + OCC + FDIC + FTC + Federal Reserve + FinCEN enforcement-related actions' — and the tagline 'Eight regulators, one tool' makes the scope unmistakable against siblings like get_epa_enforcement or get_osha_enforcement. An agent can tell exactly what this tool aggregates 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 Guidelines5/5

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

Explicitly enumerates trigger scenarios ('recent SEC charges, DOJ indictments, CFTC derivatives/swaps enforcement, ... insider trading prosecutions, FCPA actions') and names the specific condition for cross-checking ('to add a negative event flag'). It also closes with cross-source guidance naming two sibling tools (get_insider_transactions, get_activist_stakes) and when to pair them.

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

get_epa_enforcementA
Read-only
Inspect

Returns EPA federal CIVIL enforcement cases from ICIS FE&C (the EPA's Integrated Compliance Information System) via the ECHO bulk download — ~135K cases, EPA-lead administrative and judicial civil actions. CRIMINAL prosecutions are NOT in this source, and neither are state-lead actions. Refreshed weekly by EPA (~Saturday). Use this when the user asks about: EPA fines / penalties against a company, Clean Air Act / Clean Water Act / RCRA / Superfund enforcement, environmental violations by facility or state, settlements and consent decrees, or supplemental environmental projects (SEPs). Record shape (one doc per case, joins pre-flattened): case_number (RR-YYYY-NNNN), case_name, defendants[] (names), statutes[] + primary_statute (CWA, CAA, FIFRA, SDWA, RCRA, TSCA, CERCLA, EPCRA), activity_type ('administrative' | 'judicial'), activity_status + status_date, penalties from the CASE_PENALTIES table — fed_penalty, state_local_penalty, sep_amount, compliance_action_cost, cost recoveries, penalty_collected — settlement_lodged_date (earliest; only ~34% of cases lodge, mostly judicial) + settlement_entered_date (latest) + settlements_count, facilities[] (name, city, state, NAICS, FRS registry ID), region_code, doj_docket_number, enf_outcome, voluntary_self_disclosure, multimedia, summary_text, and source_url (the ECHO case report page). Date filters (since/until) and the default sort use status_date — the case's last status-change date, present on every case. Sorting by fed_penalty cannot be combined with since/until (numeric field). Cross-source: pair with get_enforcement_actions (press-release actions from 8 other regulators), get_federal_contracts (whether an EPA defendant still wins federal awards), and get_material_events (8-K environmental-liability disclosures). Pure-publisher posture: EPA's case records as published — no derived severity scores or compliance opinions.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNostatus_date lower bound (YYYY-MM-DD inclusive).
stateNoTwo-letter state code of a named facility (e.g., 'TX'). Derived from the case's facilities.
untilNostatus_date upper bound (YYYY-MM-DD inclusive).
sort_byNoDefault: status_date. fed_penalty surfaces the largest federal penalties (cannot be combined with since/until).
sort_orderNoDefault: desc.
case_numberNoDirect lookup by ICIS case number, format RR-YYYY-NNNN (e.g., 'HQ-1998-0303').
fiscal_yearNoEPA fiscal year of the case (e.g., 2024).
min_penaltyNoOnly cases with fed_penalty >= this amount (USD).
activity_typeNoadministrative = EPA's own formal actions (~93% of cases); judicial = DOJ-filed civil court cases.
defendant_nameNoCase-insensitive substring against defendant names + case name (e.g., 'caterpillar', 'exxon').
primary_statuteNoLead statute code (RANK_ORDER=1): CWA (Clean Water Act), CAA (Clean Air Act), FIFRA (pesticides), SDWA (drinking water), RCRA (hazardous waste), TSCA (toxic substances), CERCLA (Superfund), EPCRA (right-to-know). Rare others: AIM, MPRSA, MWTA.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds valuable non-obvious behavior: refresh cadence (weekly, ~Saturday), publisher posture with no derived severity scores, source exclusion constraints, and the sort_by/filter incompatibility. It doesn't discuss pagination depth or result-size limits beyond the schema, which keeps 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?

Front-loaded with the source identity and exclusions, followed by use-cases, record shape, and filter caveats in a logical order. It is long and information-dense, but nearly every clause earns its place; the record-shape enumeration is the bulkiest part and slightly exceeds what an agent needs upfront.

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 read-only query tool with no output schema, the description covers source scope, exclusions, refresh timing, record semantics (including which fields join pre-flattened), date-filter semantics, sort restrictions, and cross-source complements. 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.

Parameters4/5

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

Schema coverage is 100%, so baseline would be 3, but the description adds meaningful semantics beyond the schema: status_date is defined as the case's last status-change date present on every case, fed_penalty cannot be combined with since/until, and the settlement-lodging prevalence (~34%, mostly judicial) is surfaced. That is genuine added meaning over the structured fields.

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 verb (Returns) and resource (EPA federal civil enforcement cases from ICIS FE&C via ECHO bulk download), quantifies scope (~135K cases), and explicitly distinguishes this source from siblings by excluding criminal prosecutions and state-lead actions. An agent can immediately tell it apart from get_enforcement_actions and get_osha_enforcement.

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 an explicit when-to-use trigger list (EPA fines, CAA/CWA/RCRA/Superfund enforcement, settlements, SEPs) plus explicit exclusions and cross-source pairing guidance (get_enforcement_actions, get_federal_contracts, get_material_events). This is close to ideal routing guidance.

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

get_fda_approvalsA
Read-only
Inspect

Returns FDA approval / clearance events: drug approval actions from Drugs@FDA, medical-device 510(k) clearances, and device PMA (premarket approval) decisions. Full history (drugs to 1939, 510(k) to 1976, PMA to the 1960s). This is the BULLISH twin of get_product_recalls — the catalyst dataset for biotech and medtech tickers. Use this when the user asks about: new drug approvals for a company or ingredient, priority-review approvals, tentative generic (ANDA) approvals, device clearances by company or product code, PMA supplements, or to pair an approval date with insider trades / 8-K filings / fundamentals. Sources (filter via the source enum): drugsfda — Drugs@FDA submission actions. One record per submission decision (ORIG = original approval, SUPPL = supplemental). decision_code: AP (approved) | TA (tentative approval — generic approved but blocked by patent/exclusivity). review_priority: PRIORITY | STANDARD — PRIORITY reviews are the higher-signal events. application_number prefix tells the product class: NDA (new drug), ANDA (generic), BLA (biologic). 510k — Device premarket notifications. decision_code SESE ('substantially equivalent' — cleared) dominates ~98%. approval_type: Traditional | Special | Abbreviated. pma — Device premarket approvals (Class III, highest-risk devices — implants, life-sustaining). Originals AND supplements (supplement_number, supplement_reason). decision_code: APPR (approved) | OK30 (30-day supplement accepted) dominate. openFDA ships no description text for PMA codes; decision_description mirrors the code. review_priority='EXPEDITED' marks devices under expedited review; 'PRIORITY' marks priority-review drugs. Empty = standard / not flagged. Company matching: applicant is a substring filter on the sponsor / applicant name AS FILED (e.g., 'Pfizer', 'Boston Scientific'). FDA records carry no ticker or CIK — subsidiaries file under their own names, so try the operating-company name, not the holding company. source_url points at the accessdata.fda.gov detail page (approval letters, labels, review documents). Pure-publisher posture: no derived 'approval odds' or price-impact signals.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect lookup ('drugsfda-{applNo}-{subType}{n}', '510k-{kNumber}', 'pma-{pmaNumber}-{suppl|ORIG}'). Fastest path.
limitNoMaximum events to return. Default 50, max 500.
sinceNoDecision date lower bound (YYYY-MM-DD inclusive).
untilNoDecision date upper bound (YYYY-MM-DD inclusive).
sourceNoFilter to one feed: drugsfda (drug approval actions), 510k (device clearances), pma (Class III device approvals).
categoryNoCoarser filter: drug (= drugsfda) or device (= 510k + pma together).
applicantNoCase-insensitive substring against the sponsor / applicant company name (e.g., 'pfizer', 'medtronic').
sort_orderNoDefault: desc (most recent decisions first).
product_codeNoExact FDA device product code (e.g., 'OLO', 'MNQ'). Devices only.
product_nameNoCase-insensitive substring against product/trade/device name AND generic name / active ingredients (e.g., 'semaglutide', 'stent').
decision_codeNoExact decision code: AP / TA (drugs), SESE etc. (510k), APPR / OK30 etc. (PMA).
review_priorityNoPRIORITY (drugs), STANDARD (drugs), or EXPEDITED (devices). The high-signal filter for catalyst hunting.
application_numberNoExact match on the FDA application number (e.g., 'NDA020123', 'ANDA213414', 'K260369', 'P250013').

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnlyHint, destructiveHint, openWorldHint), and the description adds genuinely new behavioral context: full historical depth, the sponsor-name matching caveat (no ticker/CIK, subsidiaries file under own names), and the explicit 'pure-publisher posture: no derived approval odds' disclaimer. It omits return/pagination behavior, but that is minor given the annotation coverage.

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 scope are front-loaded, and virtually every sentence carries information. The source-feed block is verbose and heavily indented, pushing length well beyond what most callers need, but the density is justified by the 13-parameter surface and four enums.

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 13-parameter, zero-required, no-output-schema tool spanning three FDA feeds, the description covers source semantics, decision codes, matching behavior, historical ranges, and data provenance. 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.

Parameters5/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 substantial interpretive meaning beyond the schema: decision_code semantics (AP vs TA tentative approvals blocked by patent), application_number prefixes denoting product class (NDA/ANDA/BLA), and review_priority as the 'high-signal filter for catalyst hunting.' This is far beyond what the schema fields state.

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 precise verb+resource ('Returns FDA approval / clearance events') and enumerates the three concrete feeds (Drugs@FDA actions, 510(k) clearances, PMA decisions). It explicitly distinguishes itself from a sibling by naming get_product_recalls as its 'BULLISH twin,' so an agent can route 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 Guidelines5/5

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

Provides an explicit trigger list ('Use this when the user asks about: new drug approvals... priority-review approvals... device clearances by company or product code... PMA supplements') and even names cross-tool pairing targets (insider trades, 8-K filings, fundamentals). This is clear when-to-use guidance with an alternative named.

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

get_fec_candidate_profileA
Read-only
Inspect

Returns FEC-registered candidate profiles (House, Senate, President) and — when include_committees=true (default) — each candidate's associated FEC committees in the same response. Use this when the user asks about: who's running in race X, the campaign finance ID for a member, what PAC is sponsoring a candidate, or to bridge from a Congressional member name to their FEC committee_id before looking up contributions (v1.1 tool). Source: api.open.fec.gov — the official Federal Election Commission public-disclosure API. Records include current sitting members, primary challengers, defeated candidates, future-cycle registrants, and presidential candidates. Cycles tracked: 2022, 2024, 2026. Filter by candidate_id for the fastest direct lookup. Otherwise use candidate_name (case-insensitive substring) optionally narrowed by office + state + cycle. FEC names are typically filed as LASTNAME, FIRSTNAME (e.g., 'MCCORMICK, DAVE' for Dave McCormick). Office codes: H (House), S (Senate), P (President). Party codes: DEM (Democratic), REP (Republican), LIB (Libertarian), GRE (Green), IND (Independent), OTH (Other). Incumbent_challenge: I (Incumbent), C (Challenger), O (Open seat). When active_only=true, only candidates with candidate_status='C' (currently filing) are returned. Committee designations on returned committees: P (Principal campaign committee — the primary donation recipient), A (Authorized — accepts donations on candidate's behalf), B (Lobbyist), D (Leadership PAC), J (Joint fundraiser), U (Unauthorized). The Principal (P) committee is the one you want for 'donations to X's campaign'. Committee types: H (House campaign), S (Senate campaign), P (Presidential campaign), Q (PAC qualified), N (PAC non-qualified), O (Super PAC), I (Independent expenditure non-PAC), X/Y/Z (Party), V/W (Carey/hybrid). For 'follow the money to Senator X', look for designation=P, committee_type=S among the returned committees.

ParametersJSON Schema
NameRequiredDescriptionDefault
cycleNoElection cycle year (e.g., 2026). Returns candidates whose cycles[] includes this value. Common cycles: 2022, 2024, 2026.
limitNoMaximum candidates to return. Default 50, max 500.
partyNoParty code: DEM | REP | LIB | GRE | IND | OTH.
stateNo2-letter state abbreviation (e.g., 'PA', 'CA'). Empty for President. Combine with office=S to find the senators from a state.
officeNoOffice code: H=House, S=Senate, P=President. Narrows ambiguous name matches.
sort_byNoSort key. Default: last_file_date (most recent first).
districtNoHouse district as 2-digit string ('01'-'53') or 'AL' for at-large. Senate/President leave blank.
sort_orderNoDefault: desc.
active_onlyNoWhen true, restricts to candidate_inactive=false (currently active filers). Default false (includes withdrawn / defeated / inactive).
candidate_idNoFEC-assigned candidate ID (immutable across cycles), e.g., 'S6PA00091' for Pat Toomey, 'P80003338' for Mitt Romney's 2008 presidential bid. Direct doc lookup, fastest path.
candidate_nameNoCase-insensitive substring against the FEC-filed candidate name (typically LASTNAME, FIRSTNAME format). Example: 'mccormick' or 'collins'.
include_committeesNoWhen true (default), each returned candidate is enriched with a `committees` array containing all FEC committees linked via candidate_ids[]. The principal campaign committee (designation='P') is listed first. Set false to skip the committee fetch for faster responses when you only need candidate profile fields.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/openWorldHint/destructiveHint=false, so the safety profile is covered. The description still adds real behavioral context beyond that: the default include_committees=true triggers a committee enrichment fetch, the cycles tracked (2022/2024/2026), and that active_only=true restricts to status='C'. It does not discuss pagination or rate limits, so a 4 rather than 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?

Front-loaded with purpose and usage triggers before the reference-code detail, and most sentences earn their place. However the office codes, party codes, and incumbent_challenge codes restate enums already present in the schema, adding length without 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?

For a 12-parameter, zero-required, no-output-schema tool, the description covers lookup strategy, filtering dimensions, default behaviors, and the FEC domain code systems an agent would otherwise have to guess. Nothing needed 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?

Schema coverage is 100%, so baseline is 3; the description nonetheless adds meaning beyond the schema by explaining the LASTNAME, FIRSTNAME filing convention, the designation=P 'principal committee is the one you want for donations' heuristic, and committee_type semantics for following money. The office and party code lists largely duplicate the schema enums, which caps this below 5.

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 (FEC-registered candidate profiles plus their committees) and clearly bounds scope: House, Senate, President. It also implicitly distinguishes itself from the sibling contribution/disbursement tools by naming itself the bridge to committee_id, so an agent can place it 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 Guidelines5/5

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

Gives explicit triggering questions ('who's running in race X', 'the campaign finance ID for a member', 'what PAC is sponsoring a candidate') and the workflow position ('bridge from a Congressional member name to their FEC committee_id before looking up contributions'). It also states the fastest lookup path (candidate_id) versus the name-based path.

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

get_fec_contributionsA
Read-only
Inspect

Returns FEC Schedule A contribution data — money flowing INTO federal committees — in AGGREGATED form. Individual donors are never exposed as searchable per-record rows: the FEC sale-or-use rule (11 CFR 104.15) permits aggregated presentation only, so this tool serves group totals and a bounded ORGANISATION leaderboard (the same posture as Quiver Quantitative's public pages). Source: api.open.fec.gov (official FEC API), queried live per request with a cached-rollup fallback (responses carry source: live | cache). THREE MODES (pick one): 1. Aggregate totals — pass group_by: - group_by='employer' + recipient_committee_id + cycle → total + count per employer for that committee (FEC-computed, all itemized rows). E.g. which employers' workforces fund committee X. - group_by='state' + recipient_committee_id + cycle → geographic fundraising pattern for a committee. ⚠ On employer and state rows, contribution_count is the number of CONTRIBUTIONS, not contributors — the FEC publishes no contributor count for these aggregates. A cell can carry a dozen contributions from ONE person (measured: an employer cell with 14 contributions and a single contributor). Do not read it as a crowd, and do not use it to judge whether a cell describes a population or an individual. - group_by='candidate' + cycle (optionally candidate_id) → per- candidate cycle receipts, itemized-individual share, disbursements, cash on hand. Sorted by receipts DESC — 'who raised the most'. - group_by='committee' + recipient_committee_id (cycle optional) → that committee's cycle totals. Top-committee LISTS come from the rollup cache and may lag a day. - group_by='cycle' + candidate_id or recipient_committee_id → per-cycle rows across cycles (fundraising trajectory). 2. Donor leaderboard — pass leaderboard=true + cycle + EXACTLY ONE scope: recipient_committee_id | candidate_id | contributor_state | contributor_employer. Returns top ORGANISATION donors (PAC / party / committee / company) as name + summed total + contribution count, PLUS the individual side as STATISTICS ONLY: individual_donor_count and individual_total. NO median and NO maximum are served — each is one person's number (a median over an odd count IS one contributor's gift) and re-identifies against the FEC's own site. ⚠ SMALL-CELL FLOOR: when fewer than 5 distinct individuals contributed in the scope, the whole individual block is WITHHELD — count and total both null, suppressed=true, and the envelope carries suppressed_small_cells. Three donors plus a total is three people's gifts nearly reconstructed, and the scope is public. The organisation board is never floored; entities are not natural persons. NO NATURAL PERSON IS NAMED BY THIS TOOL, IN ANY MODE. A paid service ranking named individuals by their contribution history is a prohibited commercial use of contributor lists (11 CFR 104.15; 52 U.S.C. 30111(a)(4)). An empty organisation list means no organisation gave in that scope above the floor — it is never a reason to look for people. No addresses, no city/ZIP, no per-record rows. The response's leaderboard.complete flag is true when every itemized row at or above the fixed $1,000 floor (min_amount is not accepted in this mode) for the scope was aggregated — totals are then exact; otherwise the pull hit its page cap and ranks are amount-weighted approximations. 3. Per-record (NON-INDIVIDUAL only) — pass entity_type (COM, CCM, PAC, PTY, ORG) with optional recipient_committee_id / candidate_id / contributor_state / cycle / amount / date filters, or sub_id for a direct lookup. Individual (IND) rows are never returned per-record; memo subtotals are excluded by default (exclude_memos=false to include). Useful for PAC-to-PAC transfer analysis. There is NO contributor_name search and no individual street/city/ZIP anywhere in this tool's output — by design, permanently. Killer query patterns: - Who raised the most this cycle? group_by='candidate' + cycle=2026. - Who funds Senator X? get_fec_candidate_profile → principal committee → leaderboard=true + recipient_committee_id + cycle. - Which employers' staff fund committee Y? group_by='employer' + recipient_committee_id + cycle. - Where does committee Y's money come from? group_by='state' + recipient_committee_id + cycle. - PAC-to-PAC flows into committee Z? entity_type='PAC' + recipient_committee_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
cycleNoElection cycle year (2-year transaction period, e.g. 2026). Required for leaderboard and group_by='employer'/'state'; defaults to the current cycle for group_by='candidate'.
limitNoMax rows (aggregate/per-record) or max ORGANISATIONS (leaderboard, default 100). Default 50, max 500.
sinceNoPer-record mode: inclusive lower bound on contribution_receipt_date (YYYY-MM-DD).
untilNoPer-record mode: inclusive upper bound on contribution_receipt_date (YYYY-MM-DD).
sub_idNoPer-record mode: direct doc lookup by FEC sub_id. Returns the row only when it is a non-individual contribution.
sort_byNoPer-record mode sort key. Default: contribution_receipt_date.
group_byNoAggregate mode: group totals by this axis. employer/state require recipient_committee_id + cycle (the FEC computes those per committee). cycle requires candidate_id or recipient_committee_id.
max_amountNoPer-record mode: inclusive upper bound on amount.
min_amountNoLeaderboard: itemization floor for aggregated rows (default 1000; 200 = FEC itemization floor). Per-record: inclusive lower bound on amount.
sort_orderNoPer-record mode: default desc.
entity_typeNoPer-record mode selector — NON-INDIVIDUAL types only: COM (committee), CCM (candidate committee), PAC, PTY (party), ORG (organization). IND, UNK and CAN are not accepted: a CAN row is the FEC's code for a CANDIDATE, who is a natural person, so candidate contributions are served aggregated only alongside every other individual.
leaderboardNoLeaderboard mode: top ORGANISATION donors (PAC / party / committee / company) by name + summed total + count for ONE bounded scope, PLUS the individual side as statistics only (count and total — NO median and NO maximum; each is one person's number and re-identifies against the FEC's own site). Those statistics are WITHHELD ENTIRELY when fewer than 5 distinct individuals contributed in the scope. NO NATURAL PERSON IS NAMED — ranking named individuals by their giving is a prohibited commercial use of contributor lists (11 CFR 104.15). Requires cycle + exactly one of recipient_committee_id | candidate_id | contributor_state | contributor_employer.
candidate_idNoFEC candidate ID (e.g. 'S8GA00180'). Scope for group_by='candidate'/'cycle', leaderboard scope, or per-record filter.
exclude_memosNoPer-record mode: when true (DEFAULT) filters out memoed_subtotal rows (FEC duplicates that double-count dollars). Leaderboards always exclude them.
contributor_stateNo2-letter state code. Leaderboard scope (top donors from a state) or per-record filter (non-individual rows).
contributor_employerNoEmployer name (FEC substring match). LEADERBOARD SCOPE ONLY — top donors reporting this employer. Not available as a per-record filter.
recipient_committee_idNoFEC committee ID (e.g. 'C00401224'). Scope for group_by='employer'/'state'/'committee'/'cycle', leaderboard scope, or per-record filter. Use get_fec_candidate_profile to find a candidate's principal committee.

TDQS

A4.8/5.0
Behavior5/5

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

Far exceeds the annotation baseline (readOnly/openWorld only). It discloses a cached-rollup fallback with a source: live|cache flag, day-lag on rollup lists, the complete flag vs page-cap approximation, the small-cell withholding floor (<5 individuals → suppressed_small_cells), memo-subtotal exclusion defaults, and the $1,000 itemization floor. Consent-vs-cost warnings (contribution_count is contributions, not contributors) go well beyond structured fields.

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 before any details, and the numbered mode structure with ⚠ callouts and example queries is easy to scan. It is long, and the 'NO NATURAL PERSON IS NAMED' prohibition is restated at least three times across the text, which is padding even for a compliance-sensitive tool.

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 17-parameter, three-mode, no-output-schema tool, the description is complete: it explains mode selection, required combinations, response envelope flags (source, complete, suppressed_small_cells), and what is structurally absent from output (no addresses, no per-record individual rows). An agent needs nothing further to call it correctly.

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 real meaning the schema cannot: which parameters combine into each of the three modes, that contributor_employer is leaderboard-scope-only, and that min_amount is ignored in leaderboard mode. It does not restate every field, which is appropriate when the schema already carries it.

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 gives a specific verb, resource and scope: 'Returns FEC Schedule A contribution data — money flowing INTO federal committees — in AGGREGATED form.' It immediately distinguishes itself from siblings (get_fec_disbursements covers money out, get_fec_candidate_profile is a lookup) and the three-mode structure makes the output shape unambiguous.

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 enumerates three modes with the exact parameters each requires, states what is not accepted (min_amount in leaderboard mode, contributor_employer as a per-record filter), and closes with five 'killer query patterns' that route the agent to the right mode. Alternatives and prerequisites are named, not inferred.

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

get_fec_disbursementsA
Read-only
Inspect

Returns FEC Schedule B disbursements — itemized records of money flowing OUT of a federal committee to organisations: vendor payments, media / ad buys, consulting firms, payroll services, and committee-to-committee transfers. The OUT-flow counterpart to get_fec_contributions (Schedule A, money IN). ORGANISATIONS ONLY: per-record rows are served only when FEC codes the payee as a committee or organisation (COM, CCM, PAC, PTY, ORG). Rows naming a natural person — individual payees (IND), candidates (CAN), unclassified payees, and people a filer coded as an organisation — are withheld per record under the FEC sale-or-use rule (11 CFR 104.15). Refunds of contributions to individuals are withheld with them. Source: api.open.fec.gov/v1/schedules/schedule_b/ — the official FEC public-disclosure API. Live queries cover every itemized row; the cached fallback subset carries a $1,000+ ingestion floor (filters small-vendor / payroll noise). Publication-lag caveat: disbursements only surface when the spending committee FILES its report — monthly filers lag ~20 days, quarterly filers up to ~50 days after the spend. Short since/until windows on recent dates will miss rows whose reports haven't been filed yet. Killer query patterns: - What does candidate X's campaign spend money on? Pass spender_committee_id (their principal campaign committee from get_fec_candidate_profile). Sort by amount DESC for big spends. - Which campaigns pay consulting firm Y? Pass recipient_name='Y'. - Ad-spending patterns: disbursement_purpose_category='ADVERTISING' + cycle=2026 + sort_by=disbursement_amount DESC. - Money moving between committees: disbursement_purpose_category= 'TRANSFERS' — recipient_committee_id on each row names the receiving committee. Filter combinations note: server-side indexes support one equality filter (spender_committee_id / candidate_id / disbursement_purpose_category / recipient_state) combined with date or amount sort + cycle. Other filters (recipient_name substring, entity_type, exclude_memos) are applied client-side after a wider pre-fetch. Purpose categories (disbursement_purpose_category): ADVERTISING, CONSULTING, CONTRIBUTIONS, FUNDRAISING, PAYROLL (labeled 'SALARIES' on some rows), TRANSFERS, TRAVEL, ADMINISTRATIVE, MATERIALS, EVENTS, LOANS, REFUNDS, POLLING, OTHER. Memo rows: FEC tags certain aggregate / subtotal rows with memoed_subtotal=true. These DUPLICATE dollars already counted on other rows — KeyVex DEFAULTS to exclude_memos=true to show real money movement; pass exclude_memos=false to include the raw memo rows (e.g. for matching FEC's own row counts).

ParametersJSON Schema
NameRequiredDescriptionDefault
cycleNoElection cycle year (2-year transaction period). Common values: 2026, 2024, 2022.
limitNoMaximum disbursements to return. Default 50, max 500.
sinceNoInclusive lower bound on disbursement_date (YYYY-MM-DD).
untilNoInclusive upper bound on disbursement_date (YYYY-MM-DD).
sub_idNoFEC sub_id (globally unique row ID). Direct doc lookup, fastest.
sort_byNoSort key. Default: disbursement_date.
max_amountNoInclusive upper bound on disbursement_amount.
min_amountNoInclusive lower bound on disbursement_amount in dollars. KeyVex's cached subset holds $1,000+ rows; live queries cover every itemized row.
sort_orderNoDefault: desc (most recent / largest first).
entity_typeNoRecipient entity type code — ORGANISATION types only: COM (committee), CCM (candidate committee), PAC, PTY (party), ORG (organization — most vendors). IND (individual), CAN (candidate — a natural person) and UNK (unclassified) are not accepted: those rows are withheld under 11 CFR 104.15.
candidate_idNoFEC candidate ID tied to the disbursement (e.g., 'S6PA00091'). NOTE: only populated on candidate-linked rows; most vendor payments carry no candidate_id — prefer spender_committee_id for a campaign's full spending picture.
exclude_memosNoWhen true (DEFAULT), filters out rows flagged memoed_subtotal=true — FEC's aggregate / subtotal duplicates that double-count the same dollars across multiple rows. Pass exclude_memos=false to include them (useful for matching FEC's own raw row counts).
recipient_nameNoCase-insensitive substring against the payee's filed name (vendor, consulting firm or committee — natural persons are withheld, so a person's name returns nothing). Substring filter (client-side on the cached path).
recipient_stateNo2-letter US state code of the recipient (e.g., 'CA', 'TX').
spender_committee_idNoFEC committee ID doing the spending (e.g., 'C00580100'). Use get_fec_candidate_profile to find the principal committee for a candidate.
disbursement_purpose_categoryNoFEC's normalized purpose bucket (e.g., 'ADVERTISING', 'CONSULTING', 'CONTRIBUTIONS', 'FUNDRAISING', 'TRANSFERS', 'TRAVEL', 'PAYROLL', 'OTHER').

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/non-destructive, yet the description adds substantial behavior the agent could not infer: per-record withholding of individual payees under 11 CFR 104.15, the $1,000+ cached-subset floor, publication lag by filer type (~20 vs ~50 days), and the memo double-counting default. These are exactly the traits that change how an agent should interpret empty results.

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?

Front-loaded and clearly sectioned, but roughly 400 words with noticeable repetition — the memo/exclude_memos behavior and the organisation-only rule are each explained in both the description and the schema, and the org-code list is restated. Length is partly justified by 16 parameters and a complex domain, but it is not 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?

For a 16-parameter, no-output-schema, high-complexity tool, the description covers the gaps an agent needs: what is withheld and why, ingestion floor, filing lag, filter execution model, and default behaviors. Nothing essential to correct invocation is missing.

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?

Schema coverage is 100% (baseline 3), but the description adds meaning beyond the schema: the full purpose-category vocabulary, the server-side vs client-side filter split, and the guidance that candidate_id is sparse so spender_committee_id is preferred for a campaign's full picture. That materially changes how parameters are chosen.

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 ('Returns FEC Schedule B disbursements') and immediately scopes the content (vendor payments, ad buys, transfers). It explicitly positions itself as 'the OUT-flow counterpart to get_fec_contributions (Schedule A, money IN)', which lets an agent separate the two siblings without reading 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?

Provides four named 'killer query patterns' with concrete parameter combinations for distinct intents (candidate spending, vendor lookup, ad-spend trends, committee transfers), plus a filter-combination note explaining which filters are server-side indexed vs client-side. Also states the one-equality-filter constraint, which is real routing guidance.

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

get_fec_independent_expendituresA
Read-only
Inspect

Returns FEC Schedule E independent expenditures — money spent BY a super PAC (or IE-only PAC) uncoordinatedly FOR or AGAINST a federal candidate. Hallmark vehicle for political ad spending since Citizens United (2010). Critical signal: support_oppose_indicator — 'S' = support, 'O' = oppose. A single candidate often has dozens of S and O entries across many super PACs in one cycle. Filter by support_oppose='O' to find attack ads; 'S' to find positive ads. Source: api.open.fec.gov/v1/schedules/schedule_e/. F24 filings (24-hour notices within 20 days of an election) and F5 (quarterly IE reports) both flow through this endpoint. Filers FEC classes as "a person or a group" (Form 5 filers, committee types I and E) are served when the filer is a group; a filer whose name is, or may be, a natural person's is withheld per record, as is any filer KeyVex holds no committee record for (FEC sale-or-use rule, 11 CFR 104.15). Killer query patterns: - Attack ads on Senator X: candidate_id='S6PA00091' + support_oppose='O' - Recent spend across a cycle: support_oppose='O' + since='2025-01-01' - Top political ad vendors: payee_name='AXIOM' (substring) - Negative spend in a race: candidate_office_state='PA' + support_oppose='O' Filter combinations note: server-side indexes support one equality filter (candidate_id / committee_id / support_oppose / candidate_office_state) + a date / amount sort. Other filters (payee_name, description, exclude_memos) are applied client-side. NOTE on cycle: the FEC leaves two_year_transaction_period null on many rows, so the cycle filter is INCOMPLETE (it undercounts) and is not currently indexed — scope a cycle by DATE instead, e.g. since='2025-01-01' for the 2026 cycle.

ParametersJSON Schema
NameRequiredDescriptionDefault
cycleNoElection cycle (2-year transaction period), e.g. 2026/2024/2022. INCOMPLETE — the FEC leaves this field (two_year_transaction_period) null on many rows, so filtering by cycle undercounts, and the cycle index is not provisioned (a cycle query currently returns INDEX_MISSING). For complete cycle coverage, scope by DATE instead: since='<cycle start>' (e.g. since='2025-01-01' for the 2026 cycle).
limitNoMax records. Default 50, max 500.
sinceNoInclusive lower bound on expenditure_date (YYYY-MM-DD).
untilNoInclusive upper bound on expenditure_date (YYYY-MM-DD).
sub_idNoFEC sub_id (globally unique row ID). Direct doc lookup.
sort_byNoSort key. Default: expenditure_date.
max_amountNoInclusive upper bound on expenditure_amount.
min_amountNoInclusive lower bound on expenditure_amount in dollars.
payee_nameNoCase-insensitive substring on the payee_name (ad agency, media buyer, vendor). Client-side filter.
sort_orderNoDefault: desc.
descriptionNoCase-insensitive substring on disbursement_description (free-text purpose of the spend, e.g., 'tv ad', 'mailer', 'digital advertising'). Client-side filter.
candidate_idNoTarget candidate being supported or opposed.
committee_idNoFEC committee that spent the money (typically a super PAC). A filer who is, or may be, a natural person returns no rows — see the description.
exclude_memosNoWhen true (DEFAULT), filters out rows flagged memoed_subtotal=true — FEC's aggregate / receipt-account duplicates that double-count the same dollars across multiple rows. Top-spender queries are misleading without this filter. Pass exclude_memos=false to include the raw memo rows.
support_opposeNo'S' = filter to ads supporting the target; 'O' = filter to ads opposing. Omit for both.
candidate_officeNoOffice of the target candidate: H/S/P.
candidate_office_stateNo2-letter state code of the target candidate (e.g., 'PA', 'TX').

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare a safe read-only profile, but the description adds rich behavior beyond them: privacy withholding for natural-person filers, memo-row double-counting, F24/F5 filing sources, incomplete cycle filtering, and the split between server-side and client-side filters. This is exactly the context an agent needs to avoid misusing the 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?

The description is front-loaded with purpose and the critical support_oppose signal, then organized into source, filter behavior, and query patterns. It is dense and long with FEC legal/background detail, but most of it earns its place for a 17-parameter domain tool; some background could be trimmed without losing meaning.

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 17 optional parameters, no output schema, and read-only annotations, the description covers source, key behavioral caveats, filter combinations, and practical query recipes. It does not describe return format or pagination, but with no output schema and safety annotations present, that omission is minor.

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; the description still adds meaning by explaining server-side indexing limits for equality filters and that other filters are applied client-side. Many simple parameters (limit, sort_by, sort_order, amount bounds) are left entirely to the schema, keeping this from a 5.

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 (returns FEC Schedule E independent expenditures) and precisely defines the domain: money spent by super PACs uncoordinatedly for or against candidates. This distinguishes it from sibling FEC tools like contributions and disbursements without requiring schema inspection.

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 extensive usage context through 'killer query patterns' and filter-combination notes, including when to use support_oppose='O' for attack ads and how to scope cycles by date. However, it does not name alternative sibling tools as explicit substitutes or state clear exclusions, so it stops short of the highest bar.

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

get_federal_contractsA
Read-only
Inspect

Returns federal contract awards from USAspending.gov — government spending data sourced from Treasury/GSA. Each record is one prime contract award (BPA Call, Purchase Order, Delivery Order, or Definitive Contract). Modifications appear as separate records. Use this when the user asks about: who's getting federal contracts, how much a specific recipient (Lockheed Martin, RTX, Raytheon, Booz Allen, etc.) won this year/quarter, contracts by industry (NAICS code) or product type (PSC code), or to cross-reference congressional trading with contract awards. Cross-source pattern (the political-alpha play): 1. get_congressional_trades(ticker:'LMT', since:'2026-01-01') — find LMT trades by members of Congress. 2. get_federal_contracts(recipient_name:'Lockheed Martin', since:'2026-01-01') — find LMT contract awards. 3. Compare timing — trades within 30 days before a major contract are the high-signal cases. ⚠ award_amount and total_outlays are NULLABLE, and total_outlays is null on MOST rows. USAspending omits Total Outlays from the search response about 75% of the time, and this tool now reports that as null rather than as $0 — a 0 here means the source really said zero. Do not do arithmetic on either field without a null check. Rows with a null value are excluded from min_amount filters and sort LAST, because a value we do not have cannot satisfy a threshold. recipient_name is a case-insensitive substring match — use the parent name ('Lockheed Martin') to catch all subsidiaries. COVERAGE — live passthrough (source:'live'): each call queries USAspending's API over the full dataset (2007-10 onward), with recipient/NAICS/PSC/min-amount/date filters applied server-side. The response's total_count is USAspending's authoritative award count for your filtered query — USE IT for volume answers (the results array is just the requested page). total_count is omitted — and coverage_warning says why — when USAspending cannot count the answer: a recipient_uei that is also the PARENT of other recipients (USAspending cannot filter to one UEI's own awards), recipient_name combined with recipient_uei, or a start_date window (sort_by start_date with since/until). Then has_more is true whenever the search stopped before the end. On USAspending outage the tool falls back to a recent cached window (source:'cache' + coverage_warning) — don't infer volume there.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date — on last_modified_date, except when sort_by is start_date, where it applies to start_date.
untilNoISO date (YYYY-MM-DD). Only records on or before this date (the same date field as since).
sort_byNoField used for ordering. since/until apply to start_date when this is start_date, and to last_modified_date for every other sort. Default: last_modified_date (most-recently-modified first).
psc_codeNoProduct or Service Code (4-character). Example: 'AR33' (R&D Space Flight Advanced Development). Exact match.
min_amountNoFilter to awards with award_amount >= this value (USD). Use to focus on large contracts.
naics_codeNo6-digit North American Industry Classification System code. Example: '541710' (R&D in Physical/Engineering/Life Sciences). Exact match.
sort_orderNoDefault: desc.
recipient_ueiNoUnique Entity Identifier (replaced DUNS in 2022). 12-character alphanumeric. Exact match: only awards made to this UEI itself. If it is also the parent of other recipients, their awards are NOT included and total_count is omitted — coverage_warning names the parent; use recipient_name with that name for the whole family.
recipient_nameNoRecipient name substring; case-insensitive match. Example: 'Lockheed Martin' matches 'LOCKHEED MARTIN CORP', 'LOCKHEED MARTIN MISSILES AND FIRE CONTROL', etc. USAspending also matches the PARENT company's name, so a parent name returns its subsidiaries' awards (e.g. Sikorsky under 'Lockheed Martin'). Combined with recipient_uei it is matched against that recipient's OWN name instead, and coverage_warning says how many awards it removed.
awarding_agencyNoThe TOPTIER awarding agency name — exact and case-sensitive; a sub-agency name (e.g. 'Defense Logistics Agency') or an abbreviation ('NASA') matches nothing. Examples: 'Department of Defense', 'National Aeronautics and Space Administration', 'Department of Health and Human Services'.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/non-destructive; the description goes far beyond by disclosing that award_amount and total_outlays are nullable (with a ~75% null rate), that nulls are excluded from min_amount and sort last, that total_count is omitted under specific conditions with coverage_warning, and that outages fall back to a cached window where volume must not be inferred. This is exactly the behavioral context annotations cannot carry.

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 purpose, then usage, then the cross-source recipe, then the caveat block — good ordering and no filler sentences. It is long, and the numbered political-alpha recipe is more verbose than strictly needed, but each section still carries usable 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 an 11-parameter tool with no output schema, the description covers return semantics (total_count as the authoritative count, results as just a page, has_more) and the failure modes (coverage_warning, cache fallback). An agent has enough to answer volume questions correctly without guessing.

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 parameters are already documented, but the description adds real meaning: recipient_name's parent/subsidiary expansion, the recipient_uei-as-parent edge case, and the interaction where null values are dropped from min_amount filtering. It reinforces rather than merely repeats 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+resource ('Returns federal contract awards from USAspending.gov'), defines the record granularity (one prime contract award, modifications as separate records), and implicitly separates itself from siblings like get_federal_grants by naming the source and award types.

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 'Use this when the user asks about' list covering recipient, NAICS/PSC, and cross-reference scenarios, plus a concrete cross-source workflow naming the sibling get_congressional_trades and the 30-day timing heuristic. Nothing about when to reach for it 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.

get_federal_grantsA
Read-only
Inspect

Returns federal GRANTS and cooperative agreements from USAspending. Distinct universe from get_federal_contracts — recipients here are universities, non-profits, state and local agencies, research labs, healthcare institutions, public-private partnerships. ⚠ award_amount and total_outlays are NULLABLE. USAspending omits Total Outlays from the search response for most grants, and this tool reports that as null rather than as $0 — a 0 means the source really said zero. Null-check before doing arithmetic. Null values never satisfy min_amount and sort last. Award type codes covered: 02 (Block Grant), 03 (Formula Grant), 04 (Project Grant — most common), 05 (Cooperative Agreement). Killer query patterns: - All NIH R01 grants this quarter: cfda_number='93.847' + since=... - State and local infrastructure funding: awarding_agency='Department of Transportation' + min_amount=1000000 - Recipient-specific grant history: recipient_name='Stanford' - Recipient by federal UEI: recipient_uei='ABC123XYZ' (most precise) Source: api.usaspending.gov — official Treasury federal-spending data. Awards covering both COVID/IIJA emergency-funding codes and routine appropriations. Pure-publisher posture: raw award data, no derived rankings or performance scores. COVERAGE — live passthrough (source:'live'): each call queries USAspending's API over the full dataset (2007-10 onward), with recipient/CFDA/min-amount/date filters applied server-side. The response's total_count is USAspending's authoritative grant count for your filtered query — USE IT for volume answers (the results array is just the requested page). total_count is omitted — and coverage_warning says why — when USAspending cannot count the answer: a recipient_uei that is also the PARENT of other recipients (USAspending cannot filter to one UEI's own grants), recipient_name combined with recipient_uei, or a start_date window (sort_by start_date with since/until). Then has_more is true whenever the search stopped before the end. Note: live cfda_number matching is against the award's FULL assistance-listings array (awards can carry several CFDAs); the cached fallback matches the primary listing only. On USAspending outage the tool falls back to a recent cached window (source:'cache' + coverage_warning) — don't infer volume there.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax records. Default 50, max 500.
sinceNoInclusive lower bound (YYYY-MM-DD) on last_modified_date — or on start_date when sort_by is start_date.
untilNoInclusive upper bound (YYYY-MM-DD), on the same date field as since.
sort_byNoSort key. since/until apply to start_date when this is start_date, and to last_modified_date for every other sort. Default: last_modified_date.
min_amountNoInclusive lower bound on award_amount in dollars.
sort_orderNoDefault: desc.
cfda_numberNoCatalog of Federal Domestic Assistance program number (e.g., '93.847' = NIH R01 research grants, '20.939' = highway safety improvement). Filter to one program.
recipient_ueiNoExact federal UEI (Unique Entity ID) — most precise: only grants made to this UEI itself. If it is also the parent of other recipients, their grants are NOT included and total_count is omitted — coverage_warning names the parent; use recipient_name with that name for the whole family.
recipient_nameNoCase-insensitive substring on the recipient's name (e.g., 'Stanford', 'Mayo Clinic'), applied by USAspending — which also matches the PARENT's name, so a parent name returns its subsidiaries' grants. Combined with recipient_uei it is matched against that recipient's OWN name instead, and coverage_warning says how many grants it removed.
awarding_agencyNoThe TOPTIER awarding agency name — exact and case-sensitive; a sub-agency name (e.g. 'National Institutes of Health') or an abbreviation ('NSF') matches nothing. Examples: 'National Science Foundation', 'Department of Energy', 'Department of Health and Human Services'.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/non-destructive, but the description discloses far more: award_amount and total_outlays are nullable, nulls mean 'source omitted' rather than $0, nulls never satisfy min_amount and sort last, and total_count may be omitted with a coverage_warning under specific filter combinations. It also explains the live-vs-cache passthrough and the fallback posture on outage, none of which is derivable from the 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?

Front-loads purpose, then behavior, then query patterns, then coverage semantics, so the agent can stop reading early. It is long, and details like the award-type code enumeration and source posture are helpful but not strictly load-bearing for invocation, which keeps it just short of a 5.

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 no output schema, the description fully carries return-value semantics: total_count as the authoritative count, results as only the requested page, has_more meaning, and coverage_warning behavior. Combined with the nullable-field guidance, an agent has everything needed to interpret and use the response correctly.

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 beyond the schema: null handling relative to min_amount/sort, and that live cfda_number matches the full assistance-listings array while the cached fallback matches only the primary listing. These are real behavioral additions rather than restatements.

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 ('Returns federal GRANTS and cooperative agreements from USAspending') and immediately distinguishes it from its closest sibling by naming get_federal_contracts and contrasting the recipient universe (universities, non-profits, agencies vs. contractors). An agent can route between the two 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 explicit query patterns (cfda_number='93.847' for NIH R01, awarding_agency + min_amount for infrastructure, recipient_uei for precision) and states exactly when to rely on total_count versus the results page. It also names the fallback condition (USAspending outage -> cached window) and warns not to infer volume there, which is genuine when-to-use guidance.

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

get_federal_register_documentsA
Read-only
Inspect

Returns Federal Register documents — the daily-published collection of US executive branch regulatory + administrative actions. Use this for: regulatory tracking (what's the SEC / EPA / FDA proposing this week?), executive order monitoring, public-comment-period tracking, lobbying tie-in (cross-reference with get_lobbying_filings for 'who's pushing which rule'), or compliance forward-look on proposed regulations. Source: federalregister.gov public REST API. Comprehensive — every Federal Register publication appears here. Document types (document_type field): 'Rule' — final regulation (in effect) 'Proposed Rule' — agency rule open for public comment 'Notice' — formal notice (sunshine acts, hearings, authorizations, determinations, etc.) 'Presidential Document' — executive orders, proclamations, memoranda Agency filtering: agency_slug uses URL-safe identifiers like 'securities-and-exchange-commission', 'environmental-protection-agency', 'food-and-drug-administration', 'federal-trade-commission'. Filter via agency_slug for exact-match; agency_name does case-insensitive substring for fuzzier 'I know the name but not the slug' lookups. Composite document numbers (e.g., '2026-09385') are GPO-assigned and stable. Direct document_number lookup is fastest. Pure-publisher posture: KeyVex returns the daily publication record as-is. No 'regulatory risk score' or 'likely-to-finalize' signals.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoSubstring against title + abstract + excerpts combined. Use for topic searches ('climate', 'ai', 'cryptocurrency').
limitNoMaximum documents to return. Default 50, max 500.
sinceNopublication_date lower bound (YYYY-MM-DD inclusive).
titleNoCase-insensitive substring against the document title.
untilNopublication_date upper bound (YYYY-MM-DD inclusive).
sort_orderNoDefault: desc (newest first).
agency_nameNoCase-insensitive substring against full agency names. Use when you don't know the slug.
agency_slugNoAgency slug for exact filter (e.g., 'securities-and-exchange-commission', 'environmental-protection-agency').
document_typeNoExact filter to one document type. 'Proposed Rule' is the high-value one for compliance forward-look.
document_numberNoGPO-assigned document number (e.g., '2026-09385'). Direct doc lookup, fastest.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint/openWorldHint/destructiveHint=false, so the safety profile is covered. The description adds genuinely useful behavioral context: 'pure-publisher posture' with no risk scoring, comprehensive coverage ('every Federal Register publication appears here'), and stable GPO-assigned document numbers. It stops short of describing return format or pagination.

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 definition, then organized into labeled blocks (use cases, source, document types, agency filtering). It is on the long side, but nearly every sentence conveys distinct operational value; only minor tightening is possible.

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 10 params, no required params, full schema coverage, and annotations covering safety, the description is nearly complete. It could say more about result shape/pagination since there is no output schema, but it does characterize the record ('returns the daily publication record as-is').

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 baseline is 3. The description adds value beyond the schema by explaining the semantics of each document_type value (Rule = in effect, Proposed Rule = open for comment, etc.) and clarifying the exact-match (agency_slug) vs substring (agency_name) distinction for agency filtering.

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 ('Returns Federal Register documents') and immediately defines what that resource is ('daily-published collection of US executive branch regulatory + administrative actions'). It is distinguishable from siblings like get_government_publications and get_lobbying_filings.

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 use cases (regulatory tracking, executive order monitoring, public-comment tracking, compliance forward-look) and cross-references a sibling ('cross-reference with get_lobbying_filings'). However, it never states when NOT to use this tool or how it differs from the nearest sibling get_government_publications.

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

get_fema_disastersA
Read-only
Inspect

Returns federal disaster declarations from OpenFEMA — every DR (major disaster), EM (emergency), and FM (fire management) declaration since 1953, one record per (declaration, designated county). ~70K records. Use this when the user asks about: hurricanes / floods / wildfires / severe storms hitting a state or county, which counties were designated for FEMA assistance, active vs closed-out disasters, or to anchor an insurance / construction / utility / muni-credit question to the official federal declaration. Record shape: fema_declaration_string ('DR-4728-CA'), declaration type + date, incident_type ('Hurricane', 'Flood', 'Fire', 'Severe Storm'...), declaration_title ('HURRICANE IAN'), designated_area (county) + FIPS codes, and the four assistance-program flags (individual_assistance, individuals_households_program, public_assistance, hazard_mitigation) — public_assistance=true is the infrastructure-rebuild-money flag. A single disaster spans MANY records (one per designated county): filter fema_declaration_string or disaster_number for all areas of one event; filter state + since for a state's recent disasters. Cross-source: follow a declaration with get_federal_contracts / get_federal_grants (recipient_name or date-windowed) for the rebuild spend, and get_material_events for insurer 8-Ks after major events. Pure-publisher posture: FEMA's declarations as published — no derived damage estimates or exposure scores.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect lookup: '{declarationString}-{fips}' (e.g., 'DR-4728-CA-06037').
limitNoMaximum records to return. Default 50, max 500.
sinceNoDeclaration date lower bound (YYYY-MM-DD inclusive).
stateNoTwo-letter state / territory code (e.g., 'FL', 'PR').
titleNoCase-insensitive substring against declaration title + designated area (e.g., 'ian', 'maui').
untilNoDeclaration date upper bound (YYYY-MM-DD inclusive).
sort_orderNoDefault: desc (most recent declarations first).
incident_typeNoExact incident type (e.g., 'Hurricane', 'Flood', 'Fire', 'Severe Storm', 'Tornado', 'Earthquake').
disaster_numberNoExact FEMA disaster number (e.g., 4728).
declaration_typeNoDR = major disaster, EM = emergency, FM = fire management.
fema_declaration_stringNoExact declaration (e.g., 'DR-4728-CA') — returns every designated county for that event.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations only declare readOnly/openWorld/non-destructive; the description adds genuine behavioral context beyond those — the ~70K record volume, the one-record-per-(declaration, county) fan-out (critical, since a single disaster spans MANY rows), and the 'pure-publisher posture' stating no derived damage estimates or exposure scores. It does not mention pagination behavior or default result ordering beyond sort_order's schema note, so a 4 rather than 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?

Measured in paragraphs: purpose/scale first, then a when-to-use trigger list, then record shape, then filter guidance, then cross-source and posture. It is dense but every section earns its place. Slightly long, keeping it off a 5.

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 11-param, no-output-schema, read-only tool, the description is complete: it defines record granularity, all major filters, the assistance-flag semantics (public_assistance as the infrastructure-rebuild-money flag), and the cross-source workflow. 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.

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 11 parameters thoroughly. The description reinforces the right filter idioms ('filter fema_declaration_string or disaster_number for all areas of one event; filter state + since for a state's recent disasters'), which adds small routing value over the schema, but nothing beyond it. 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?

The description names a specific verb (returns) and resource (federal disaster declarations from OpenFEMA), scopes it to every DR/EM/FM declaration since 1953, and states the record granularity. No sibling tool covers this data, so the purpose is unambiguous.

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 an explicit trigger list ('hurricanes / floods / wildfires ... when the user asks about ...') and names cross-source follow-ups (get_federal_contracts, get_federal_grants, get_material_events). The agent knows exactly when to reach for it and what to do next.

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

get_ferc_filingsA
Read-only
Inspect

Returns FERC eLibrary document records — every public filing at the Federal Energy Regulatory Commission: Issuances (orders, notices, delegated letters BY FERC) and Submittals (rate filings, tariff changes, compliance reports, protests, hydro license paperwork TO FERC) across the Electric, Natural Gas, Oil, Hydro, Rulemaking, and General libraries (~1,300 documents/week). Use this when the user asks about: a FERC docket or rate case, pipeline / utility / hydro regulatory activity, FERC orders affecting a company, or energy infrastructure proceedings. The DOCKET NUMBER is the join key across a proceeding. Format: PREFIX + two-digit year + sequence, e.g. 'ER26-1234' (Electric rate), 'RP26-930' (gas pipeline rate), 'CP26-15' (gas pipeline certificate/construction), 'P-5737' (hydro project — no year), 'EL26-50' (Electric complaint/investigation), 'RM26-3' (rulemaking). docket_number accepts the root ('RP26-930') or a full sub-docket ('RP26-930-000'). Records carry docket_numbers (verbatim) plus docket_prefixes for quick classification. Record shape: accession_number (e.g. '20260708-3001' — the unique document key), category ('Issuance' | 'Submittal'), description, filed/issued/posted dates, class_types (document class + type), libraries, authors[] / recipients[], and transmittal file metadata. Documents themselves are NOT in the record — agents download the primary attached file via source_url (eLibrary filedownload link). Pure-publisher posture: FERC's search metadata as published — no outcome predictions or case scoring.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoCase-insensitive substring against the document description (e.g. a company name).
limitNoMaximum records to return. Default 50, max 500.
sinceNoLower bound (YYYY-MM-DD inclusive) on the sort_by date field.
untilNoUpper bound (YYYY-MM-DD inclusive) on the sort_by date field.
libraryNoFERC library — code or name: E/Electric, G/Gas, O/Oil, H/Hydro, RM/Rulemaking, Gen/General. (Rare multi-library documents carry a concatenated value like 'RulemakingElectric' — FERC's own encoding — and only match that exact string.)
sort_byNoDefault posted_date (when FERC published the document — filings can post up to ~4 days after filing).
categoryNoIssuance = BY FERC (orders, notices); Submittal = TO FERC (company filings).
class_typeNoCase-insensitive substring against document class + type (e.g. 'order', 'tariff', 'protest', 'environmental').
sort_orderNoDefault: desc (most recent first).
docket_numberNoDocket number — root ('RP26-930', 'P-5737') or full sub-docket ('RP26-930-000'). Returns every document in that proceeding.
accession_numberNoDirect lookup by FERC accession number (e.g. '20260708-3001').

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint/openWorldHint/destructiveHint=false, yet the description adds substantial non-obvious context: the 'pure-publisher posture' (no predictions or scoring), the ~4-day posting lag, the fact that documents themselves are not in the record, and that the primary file must be fetched via source_url. That is exactly the extra-behavior detail the annotations cannot supply.

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 dense paragraphs but front-loaded with the return resource and trigger conditions before the docket-format reference material. Nearly every sentence carries operational value, though the record-shape inventory borders on schema duplication and could be tightened.

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 11-parameter, no-output-schema tool, the description compensates well: it describes the record shape (accession_number, category, class_types, libraries, authors/recipients), the join key (docket_number), and where the actual documents live. An agent has everything needed to query and interpret results.

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 goes beyond the schema by decoding the docket-number grammar (prefix + year + sequence, with concrete examples per library), explaining that sub-dockets like 'RP26-930-000' resolve to the same proceeding, and clarifying the posted_date vs filed_date lag. The library concatenation quirk ('RulemakingElectric') is also surfaced as both schema and prose.

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 ('Returns FERC eLibrary document records'), enumerates the exact scope (Issuances vs Submittals across six libraries) and quantifies volume (~1,300 docs/week). This clearly separates it from adjacent siblings like get_federal_register_documents or get_enforcement_actions, which cover different sources.

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 triggering conditions: 'Use this when the user asks about: a FERC docket or rate case, pipeline / utility / hydro regulatory activity, FERC orders affecting a company, or energy infrastructure proceedings.' No competing sibling is named for exclusion, but the tool's domain is narrow enough that this is clear context rather than an omission.

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

get_foreign_agentsA
Read-only
Inspect

Returns FARA registrations — US persons and firms registered with the DOJ as agents of a foreign principal under the Foreign Agents Registration Act. Use this when the user asks about: who is a registered foreign agent, which US firms work for a particular foreign government, recently-registered foreign agents, or to add a 'foreign- influence' flag to a lobbying firm, law firm, or PR firm. Each record is one registrant ↔ foreign-principal relationship — a registrant representing three foreign principals appears as three records. The single highest-signal filter is foreign_principal_country: foreign_principal_country='CHINA' → every US agent acting for a Chinese principal Source: efile.fara.gov (DOJ National Security Division). v1A covers ACTIVE registrations. The registrant↔principal linkage is included; per-document filing detail and compensation figures are not — follow source_url to FARA eFile for those. Cross-source pairing pattern: FARA + get_lobbying_filings — FARA is foreign-principal representation; LDA is domestic lobbying. A firm in both is lobbying Congress on behalf of a foreign government. FARA + get_fec_contributions — foreign-agent firms whose people also make political contributions. FARA + get_congressional_trades — influence-and-trades overlay. Identifier: registration_number is the FARA registration number. has_foreign_principal=false records are registrants with no currently- active foreign principal (still queryable as registered agents). History: registrations that LEAVE DOJ's active list are kept with status:'terminated' (+ termination_observed_date) rather than deleted — a terminated registration is still real history. Default queries return BOTH; filter status:'active' for the current roster only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, by sort_by.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
statusNoRegistration status: 'active' = currently on DOJ's list; 'terminated' = left the list since ingestion (kept as history). Omit for both.
sort_byNoDefault: registration_date.
sort_orderNoDefault: desc (most recent first).
registrant_nameNoCase-insensitive substring against the US registrant (agent) name.
registration_numberNoExact FARA registration number. Fastest lookup.
has_foreign_principalNoFilter to records that carry a foreign-principal relationship (true) or registrants with no active foreign principal (false).
foreign_principal_nameNoCase-insensitive substring against the foreign principal's name.
foreign_principal_countryNoCountry of the foreign principal, matched uppercase (e.g. 'CHINA', 'RUSSIA', 'SAUDI ARABIA'). The key foreign-influence filter.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover read-only, open-world, and non-destructive behavior, but the description adds substantial context beyond that: record-level granularity, v1A scope, what is included (registrant ↔ principal linkage) versus excluded (per-document filing detail and compensation figures), retention of terminated registrations, and the meaning of has_foreign_principal=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?

The description is long but front-loaded with purpose and usage, and most sentences carry useful domain-specific guidance. It is more verbose than necessary for a tool definition, but the structure and density of information justify most of its length.

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 11 parameters, no output schema, and annotations that cover only the safety profile, the description is highly complete. It explains scope, key filters, return granularity, exclusions, historical retention, and complementary tools so an agent can invoke it correctly without guessing.

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 the schema already documents all 11 parameters and a baseline of 3 is appropriate. The description adds extra meaning for key filters—especially foreign_principal_country as the highest-signal filter with a concrete example, status behavior, and has_foreign_principal semantics—but does not add much beyond the schema for the remaining parameters.

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: returns FARA registrations of US persons/firms registered with DOJ as foreign agents. It clearly distinguishes itself from siblings by naming FARA as foreign-principal representation versus LDA as domestic lobbying, and it explains the record granularity (one registrant ↔ foreign-principal relationship per record).

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 use cases (who is a registered foreign agent, which US firms work for a particular foreign government, recently registered agents, adding a foreign-influence flag) and cross-source pairing patterns with get_lobbying_filings, get_fec_contributions, and get_congressional_trades. It also states that default queries return both active and terminated registrations, and that status:'active' should be used for the current roster only.

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

get_fundamentalsA
Read-only
Inspect

Returns XBRL-tagged financial fundamentals from public-company 10-K and 10-Q filings, sourced from SEC EDGAR's company-facts API. Each record is one observation of one concept at one period end. Use this when the user asks about: revenue, profit, margins, cash position, debt, shareholder equity, EPS, share count, operating vs. financing cash flow, or any line-item-level financial state of a public company. v1A scope: a curated 40-concept watchlist covering: - income_statement: Revenues / RevenueFromContractWithCustomer / CostOfRevenue / GrossProfit / OperatingExpenses / R&D / SG&A / OperatingIncomeLoss / InterestExpense / IncomeTaxExpenseBenefit / NetIncomeLoss - balance_sheet: Assets / AssetsCurrent / Cash / AccountsReceivable / Inventory / PP&E / Goodwill / Liabilities / LongTermDebt / StockholdersEquity / CommonStockSharesOutstanding - cash_flow: NetCash{Operating/Investing/Financing}Activities / PaymentsToAcquirePPE (capex) / PaymentsForRepurchaseOfCommonStock / PaymentsOfDividends / DepreciationDepletionAndAmortization - metrics: EarningsPerShareBasic/Diluted, weighted-avg share counts - entity: EntityCommonStockSharesOutstanding (dei taxonomy) Key cautions on the data: - The same concept can appear in multiple units (e.g., 'USD' and 'USD/shares' for EPS). Filter by unit if you need a specific shape. - Many concepts have BOTH year-to-date cumulative observations AND quarterly-period observations on 10-Q filings. The frame field (e.g., 'CY2025Q3') marks the per-quarter point-period observation; rows with empty frame are typically cumulative YTD. - Older filings may use deprecated concept names; KeyVex catalog includes both modern and legacy names where companies migrated (e.g., Revenues AND RevenueFromContractWithCustomerExcludingAssessedTax). Set latest_only=true to get one record per (ticker × concept) — the most-recent observation. Useful for 'current state' snapshots. Pure-publisher posture: values are AS FILED. We do NOT compute derived ratios (P/E, ROE, ROIC), YoY/QoQ deltas, or 'real' vs nominal versions. Agents calculate those on top.

ParametersJSON Schema
NameRequiredDescriptionDefault
formNoFilter to one filing form.
limitNoDefault 50, max 500.
sinceNoISO date YYYY-MM-DD. Applied to sort_by field.
untilNoISO date YYYY-MM-DD.
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive.
conceptNoExact XBRL tag name (e.g., 'NetIncomeLoss', 'Revenues', 'Assets', 'CashAndCashEquivalentsAtCarryingValue'). Case-sensitive.
sort_byNoDefault period_end.
categoryNoBucket filter when you don't know the exact concept name.
sort_orderNoDefault desc.
company_cikNoSEC CIK number. Alternative to ticker.
fiscal_yearNoFilter to one fiscal year — the year the financials DESCRIBE (the company's own fiscal-year label, derived from the original filing), NOT the filing year. Handles non-December fiscal years: e.g. NVDA's year ending 2024-01-28 is fiscal_year 2024, Apple's ending 2024-09-28 is 2024. For point-in-time period filtering, period_end / since / until and frame are also available.
latest_onlyNoWhen true, return only the most-recent observation per (ticker × concept). Default false.
fiscal_periodNoFilter to one fiscal period.

TDQS

A4.3/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/non-destructive, and the description layers substantial extra context beyond them: unit multiplicity (USD vs USD/shares), YTD-cumulative vs quarterly observations and the frame marker, deprecated concept-name migration, latest_only collapsing to one row per ticker×concept, and an explicit 'pure-publisher' posture (no derived ratios). This is exactly the behavioral detail an agent needs and could not get from the 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?

Front-loaded with the core purpose, then organized into scope, cautions, and posture blocks that each carry distinct information. It is long and the 40-concept watchlist is verbose, but nearly every line earns its place; trimming is possible but not warranted enough to drop below a 4.

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 13 parameters, no output schema, and a specialized financial domain, the description supplies the scope (concept watchlist), the record grain, the data-interpretation hazards, and the deliberate non-computation boundary. An agent has everything required to call and interpret this tool correctly.

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 the per-parameter text already carries the basics. The description still adds meaning on top: it explains latest_only's per-ticker×concept collapse, lists the concept categories behind the category enum, and clarifies the frame/period semantics that govern how results should be interpreted.

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?

States a specific verb and resource: 'Returns XBRL-tagged financial fundamentals from public-company 10-K and 10-Q filings, sourced from SEC EDGAR's company-facts API,' and clarifies the record grain ('one observation of one concept at one period end'). It never names distinguishing siblings such as get_annual_financial_disclosures or get_bank_financials, so an agent must infer the boundary rather than being told it.

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 an explicit trigger list ('Use this when the user asks about: revenue, profit, margins, cash position, debt...') that maps user intents to the tool, which is strong positive guidance. There is no 'when-not-to-use' clause and no named alternative for overlapping needs, so routing vs siblings is left implicit.

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

get_fund_holdingsA
Read-only
Inspect

Returns per-security holdings from SEC Form N-PORT primary documents — one row per investment-or-security line in a mutual fund / ETF / closed-end fund's monthly portfolio report. Use this when the user asks about: which funds hold a specific stock or bond, a fund's complete portfolio composition, fund-level derivative exposure (swaps, options, futures), repo positions, concentration by issuer, or to compose 'which ETFs added X this month' / 'which funds shorted Y' style queries. Source: parsed from each NportFiling's primary_doc.xml. asset_cat is SEC's own code, and these twenty are the only ones the data holds — EC common equity; EP preferred equity; DBT debt, Treasuries included; LON loan; ABS-MBS asset-backed, mortgage; ABS-O asset-backed, other; ABS-CBDO asset-backed, CDO/CBO; ABS-APCP asset-backed commercial paper; SN structured note; STIV short-term investment vehicle, money-market and liquidity pools; RA repurchase and reverse-repurchase agreement; RE real estate; COMM commodity; DE equity derivative; DIR interest-rate derivative; DFE foreign-exchange derivative; DCR credit derivative; DCO commodity derivative; DO other derivative; OTHER other. Anything else is refused with this list. Useful filter combos: ticker='NVDA' all funds holding NVDA cusip='037833100' AAPL by CUSIP (more reliable than ticker for N-PORT) is_derivative=true, filer_name='BlackRock' the BlackRock FAMILY's derivative book — a name is a substring, and this one spans five trusts. filer_cik picks one of them. derivative_type='swap' every swap position in the universe asset_cat='RA' repo and reverse-repo exposure payoff_profile='Short' short positions only min_pct_of_portfolio=5 concentrated positions (>=5% of NAV) filer_cik='0000884394' one fund's complete portfolio counterparty='Morgan Stanley' every fund's exposure to one dealer min_notional=10000000 derivatives with >=$10M of EXPOSURE (not fair value — see min_notional) derivative_type='swap', expiration_until='2026-12-31' swaps rolling off before year-end maturity_since='2026-01-01', maturity_until='2026-12-31' bonds maturing this year Each holding ties to its parent NportFiling via filing_id. Read the parent for fund metadata (file_date, file_number, amendment flag); read the holding for security-level detail. is_derivative + derivative_type distinguish structured derivative rows from straight equity/debt holdings. DERIVATIVE + DEBT TERMS are extracted and filterable (2026-08-09). Derivatives carry deriv_notional_amount, deriv_counterparty_name/_lei, deriv_expiration_date, deriv_unrealized_appreciation, and the leg-level detail — put/call, written/purchased, strike, share count and delta for options; swap flag and upfront payment/receipt for swaps; both currency legs for forwards. Debt rows carry debt_maturity_date, coupon kind, annualized rate, default, arrears and paid-in-kind flags. USE min_notional, NOT min_value_usd, TO SIZE A DERIVATIVE. Fair value and exposure differ by orders of magnitude: a real interest-rate swap here shows value_usd -49,184 against a notional of 6,795,000. Ranking derivatives by value_usd understates them by ~100x. BACKFILL IN PROGRESS: these fields are populated on filings re-extracted since 2026-08-09 and are absent (null) on the rest until it completes. A null term on an older filing means not-yet-extracted, NOT absent from the source — do not read it as 'this swap has no counterparty'. The parent filing's primary_document_url always has the authoritative detail. COVERAGE: holdings begin with N-PORT filings FILED 2024-06-01. Most filings from then on have holdings rows, but not all: some are still metadata-only in get_nport_filings (not yet extracted — about 4% as of September 2026). Filings before 2024-06-01 are outside this coverage. For a filing with no holdings here, follow primary_document_url in get_nport_filings. An empty result for a filing means not-extracted, not an empty fund.

ParametersJSON Schema
NameRequiredDescriptionDefault
isinNoExact ISIN if filer included it in the identifiers block.
nameNoCase-insensitive substring against the holding issuer name (e.g., 'Apple', 'Treasury', 'Goldman Sachs').
cusipNoExact 9-character CUSIP. Most reliable identifier for equity and debt holdings in N-PORT.
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only holdings whose period_ending >= this date.
untilNoISO date (YYYY-MM-DD). Only holdings whose period_ending <= this date.
tickerNoExact ticker symbol if filer included it in the identifiers block (less common than CUSIP).
countryNoISO-2 country code of the holding (e.g., 'US', 'GB', 'JP').
sort_byNoDefault: value_usd.
asset_catNoSEC's asset-category code, case-insensitive. The data holds exactly these: EC common equity; EP preferred equity; DBT debt, Treasuries included; LON loan; ABS-MBS asset-backed, mortgage; ABS-O asset-backed, other; ABS-CBDO asset-backed, CDO/CBO; ABS-APCP asset-backed commercial paper; SN structured note; STIV short-term investment vehicle, money-market and liquidity pools; RA repurchase and reverse-repurchase agreement; RE real estate; COMM commodity; DE equity derivative; DIR interest-rate derivative; DFE foreign-exchange derivative; DCR credit derivative; DCO commodity derivative; DO other derivative; OTHER other. An unknown code is refused with the list rather than searched for — Treasuries are DBT, money-market positions are STIV, and a repurchase agreement is RA.
filer_cikNoFund trust CIK (10-digit, padded with leading zeros). Returns the trust's holdings across all reporting months. This is the precise form of filer_name: one trust, rather than a name substring that can match a whole family of them.
filing_idNoEDGAR accession number — returns all holdings from one specific N-PORT filing (one fund-month).
filer_nameNoCase-insensitive substring against fund trust name (e.g., 'iShares', 'Vanguard', 'SPDR'). ⚠ A name substring matches a FAMILY, not a fund: 'BlackRock' matches at least five separate trusts (0000893818, 0000844779, 0001761055, 0000355916, 0001804196) and 300,000+ holdings rows, so it asks for the whole family's book and reads far more than a caller usually wants. filer_cik is the precise form — one trust. To narrow a name search instead, add period_ending.
sort_orderNoDefault: desc (largest / most recent first).
counterpartyNoCase-insensitive substring against the derivative counterparty (the dealer or clearing house on the other side). Answers exposure-concentration questions — e.g. counterparty='Morgan Stanley' across funds. Cleared derivatives name an exchange or clearing house (CME, Chicago Board of Trade) rather than a bank. Note the source writes the literal 'N/A' where no counterparty is disclosed, and that value is preserved rather than nulled.
min_notionalNoMinimum derivative NOTIONAL amount in the contract's currency. This is EXPOSURE, not fair value, and for derivatives the two differ by orders of magnitude — a real interest-rate swap in this dataset carries value_usd -49,184 against a notional of 6,795,000. Use min_notional (not min_value_usd) to ask 'how big is the bet'; use min_value_usd to ask 'how much is the position worth today'. Rows with no notional are excluded by any positive floor: options carry share count + strike instead and legitimately have none.
is_derivativeNoTrue returns only derivative rows (asset_cat starting with 'D'). False returns only non-derivative rows. Omit for both.
min_value_usdNoMinimum fair value in USD. Use to focus on large positions only.
period_endingNoReporting month-end (YYYY-MM-DD). Restricts results to one reporting period.
maturity_sinceNoISO date (YYYY-MM-DD). Only debt holdings maturing on or after this date. Applies to the 33.6% of rows that are bond-like; pair with maturity_until to build a maturity ladder.
maturity_untilNoISO date (YYYY-MM-DD). Only debt holdings maturing on or before this date.
payoff_profileNoFilter to long or short positions per N-PORT payoffProfile field.
derivative_typeNoStructural derivative type, derived from which `<derivativeInfo>` child element is present in the filing.
expiration_sinceNoISO date (YYYY-MM-DD). Only derivatives expiring on or after this date. Normalized across contract types — futures expDate, option expDt, swap terminationDt, forward settlementDt all populate it, and deriv_category tells you which. Rows whose value is not a real date (the source writes 'N/A') are excluded from the window rather than compared.
expiration_untilNoISO date (YYYY-MM-DD). Only derivatives expiring on or before this date. Pair with expiration_since for a rollover window.
min_pct_of_portfolioNoMinimum percentage of fund net assets (0-100 scale). Use to focus on concentrated positions.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already mark this read-only, non-destructive and open-world, and the description layers substantial extra context on top: the 2024-06-01 coverage start, the ~4% unextracted subset, null-means-not-yet-backfilled semantics, the 'N/A' counterparty preservation quirk, and the min_notional-vs-value_usd ~100x divergence warning. These are exactly the operational caveats an agent cannot get from annotations or schema.

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?

Dense and front-loaded, but the twenty-value asset_cat enumeration is reproduced almost verbatim from the schema, and the coverage/backfill caveats are restated more than once. The filter-combo block is long but largely earns its place; the asset_cat duplication does not.

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 26-parameter, no-required-args search tool with no output schema, the description covers absolutely everything an agent needs: what a row is, how it relates to the parent filing, coverage boundaries, null/empty-result interpretation, and the derivative/debt field families added in the 2026-08-09 extraction.

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, and the description earns an extra point by explaining how parameters compose (filer_name matching a family vs filer_cik pinning one trust, min_notional vs min_value_usd for sizing, payoff_profile='Short' for short books) and by disclosing refusal/edge behavior. It stops short of syntax detail on the date-window pairs, which the schema already covers.

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 and resource — 'Returns per-security holdings from SEC Form N-PORT primary documents' — and immediately fixes the grain ('one row per investment-or-security line'). It also differentiates from the sibling get_nport_filings by explaining that the parent filing carries fund metadata while the holding carries security-level detail.

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 enumerates the question shapes this tool answers (which funds hold X, portfolio composition, derivative exposure, repo, concentration, shorted-Y queries) and then gives a long list of concrete filter combinations. It also names the alternative route — read the parent filing via filing_id / primary_document_url for metadata — and states when an empty result means 'not extracted' rather than 'no positions'.

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

get_government_publicationsA
Read-only
Inspect

Returns recent congressional + oversight publications from GovInfo across four collections. Use this when the user asks about: - Committee reports on a specific bill or topic - Recently signed public laws (the 'did it become law' signal) - Congressional hearing transcripts (testimony from regulators, CEOs, expert witnesses) - GAO oversight reports (independent reviews of federal agencies + programs, often precede SEC/DOJ enforcement on the same target) Collections (filter via the collection enum): CRPT — Congressional Reports. Includes committee reports accompanying bills (House hrpt / Senate srpt). Real- time signal on what's about to move on the floor. PLAW — Public + Private Laws. Bills that were signed into law. The 'what actually got done' record. CHRG — Congressional Hearings. Transcripts of House + Senate committee hearings — testimony from agency heads, executives, expert witnesses. Hearings often PRECEDE enforcement actions (the public 'why did this happen' conversation). GAOREPORTS — GAO oversight reports. Independent congressional oversight. NOTE: GovInfo's GAO collection is a historical archive (~16.5K reports) that is not receiving recent updates — GAO now publishes current reports on gao.gov directly. Use this for historical GAO research; recent reports won't appear here. Identifier format: each package_id is GovInfo's globally-unique ID (e.g., 'CRPT-119hrpt27' for House Report 27 of the 119th Congress, 'PLAW-119publ12' for Public Law 12, 'CHRG-119hhrg54321' for House hearing 54321). Direct doc lookup by package_id is fastest. Cross-source pairing pattern: Hearing → trade by attending member: get_congressional_trades( bioguide_id:'...', since:'') GAO report on agency → SEC follow-on: get_enforcement_actions( text:'', since:'') Committee report → bill passage: get_bills + get_roll_call_votes Full document body (PDF / HTML / XML) lives at package_link; v1A returns only metadata — agents follow the link for content.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only documents whose date_issued is on or after this date.
titleNoCase-insensitive substring against the package title.
untilNoISO date (YYYY-MM-DD). Only documents whose date_issued is on or before this date.
sort_byNoDefault: date_issued.
congressNoCongress number as string (e.g., '119').
doc_classNoSub-class within the collection. Examples: 'hrpt' (House report), 'srpt' (Senate report), 'pub' (public law), 'pvt' (private law), 'hr' (House hearing), 's' (Senate hearing).
collectionNoFilter to one collection: CRPT (committee reports), PLAW (public laws), CHRG (hearings), GAOREPORTS (GAO).
package_idNoGovInfo packageId. Direct doc lookup, fastest. Example: 'CRPT-119hrpt27'.
sort_orderNoDefault: desc (most recent first).

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the readOnly/openWorld/destructive annotations, the description discloses two non-obvious behavioral traits: the GAOREPORTS collection is a stale historical archive (~16.5K reports, no recent updates) and v1A returns metadata only with the full body at package_link. Both would materially change how an agent answers if omitted.

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 headed bullets, collections block, and pairing patterns — every section is scannable. It is however quite long (~350 words) and some collection prose is richer than strictly needed for selection.

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 no output schema, the description carries the return-value burden and does so by stating that only metadata is returned and that content lives at package_link. Combined with full collection coverage, usage triggers, and identifier format, an agent has 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.

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 genuine meaning: each `collection` enum value is given interpretive significance (CRPT as a real-time floor signal, PLAW as the 'what actually got done' record, CHRG as a precursor to enforcement), and the package_id naming convention is decoded with worked examples. The remaining date/sort/limit params are left to 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+resource (returns recent congressional + oversight publications from GovInfo) and names the exact four collections it spans. An agent can distinguish it from get_bills, get_roll_call_votes, or get_federal_register_documents from the description alone.

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?

Opens with an explicit 'Use this when the user asks about' block enumerating four triggering scenarios (committee reports, signed public laws, hearing transcripts, GAO oversight). It also routes to alternatives via named cross-source pairing patterns (get_congressional_trades, get_enforcement_actions, get_bills + get_roll_call_votes) with the condition that selects each.

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

get_h1b_filingsA
Read-only
Inspect

Returns H-1B Labor Condition Applications from the Department of Labor's quarterly disclosure files — one record per LCA with employer, job title, O*NET-SOC occupation code, offered wage vs DOL prevailing wage, worksite location, and employer risk flags (h1b_dependent, willful_violator). Covers H-1B, H-1B1 (Chile / Singapore), and E-3 (Australia) visa classes. Use this when the user asks about: a company's hiring activity or wage levels for specific roles, tech-hiring trends by state or occupation, offered vs prevailing wage gaps, or outsourcing-firm staffing patterns. IMPORTANT interpretation notes (stated so agents don't over-read): an LCA is filed BEFORE the H-1B petition and can cover multiple positions (total_worker_positions) — it signals hiring INTENT, not an approved visa or a hire. Certified ≫ actual visas issued. Wage fields are as filed; wage_unit varies (Year / Hour / Month / Week / Bi-Weekly) — normalize before comparing. Matching: employer_name is a substring over legal name + DBA (e.g., 'infosys', 'amazon'). soc_code is the precise occupation filter (e.g., '15-1252.00' Software Developers). case_status values: 'Certified', 'Certified - Withdrawn', 'Denied', 'Withdrawn'. Coverage: FY2024→present from DOL's quarterly files (fiscal_year / fiscal_quarter on each record; ~400-550K filings per quarter). Pure-publisher posture: DOL's disclosure rows as filed — no derived 'real wage' normalization or employer scoring.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNoDecision date lower bound (YYYY-MM-DD inclusive).
untilNoDecision date upper bound (YYYY-MM-DD inclusive).
soc_codeNoExact O*NET-SOC occupation code (e.g., '15-1252.00' = Software Developers).
job_titleNoCase-insensitive substring against the job title (e.g., 'machine learning').
sort_orderNoDefault: desc (most recent decisions first).
visa_classNoExact: 'H-1B', 'H-1B1 Chile', 'H-1B1 Singapore', 'E-3 Australian'.
case_numberNoDirect lookup by DOL case number (e.g., 'I-200-26083-726723').
case_statusNoExact: 'Certified', 'Certified - Withdrawn', 'Denied', 'Withdrawn'.
employer_nameNoCase-insensitive substring against employer legal name + DBA (e.g., 'google', 'tata').
worksite_stateNoTwo-letter worksite state (e.g., 'CA', 'TX').

TDQS

A4.4/5.0
Behavior5/5

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

Annotations cover only the safety profile (readOnly/openWorld/non-destructive), and the description adds substantial behavior beyond that: LCAs are pre-petition and signal intent not approval, Certified far exceeds visas issued, wage_unit varies across five units, case_status enum values, FY2024→present coverage at ~400-550K filings/quarter, and a pure-publisher no-normalization posture. This is exactly the context annotations cannot carry.

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?

Dense but front-loaded: return fields first, then usage triggers, then interpretation caveats, matching, and coverage. Length is justified by the tool's complexity, though a few clauses (e.g. the two 'e.g.' examples) repeat schema content and could be trimmed.

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 no output schema, 11 parameters, and a nuanced dataset, the description still supplies return-field inventory, interpretation caveats, coverage window, matching behavior, and wage-normalization warnings. Nothing an agent needs to call and read 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 11 parameters are already documented; baseline is 3. The description restates matching semantics (employer_name substring over legal+DBA, soc_code precise filter, case_status values) that largely duplicate the schema rather than adding syntax or default details.

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 (returns H-1B Labor Condition Applications from DOL quarterly files) and enumerates the exact record contents (employer, job title, SOC code, offered vs prevailing wage, worksite, risk flags). No sibling covers H-1B/LCA data, so the agent can place it immediately 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?

Gives explicit when-to-use triggers: company hiring activity, wage levels for roles, tech-hiring trends by state/occupation, offered-vs-prevailing gaps, outsourcing-firm patterns. Strong context, but it names no alternative tool or when-not-to-use boundary (e.g. vs unified_search).

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

get_insider_filingsA
Read-only
Inspect

A ticker search also returns rows this issuer FILED UNDER SYMBOLS IT NO LONGER LISTS (renames, filer typos, ADR spellings). Each row keeps ticker as SEC received it and gains current_ticker when the issuer trades under a different symbol today. Separately-listed share classes are NOT merged, and asking for a RETIRED symbol returns only rows filed under it — retired symbols get reissued to other companies. Returns FILING-LEVEL records from SEC Form 3/4/5 filings — one row per filing (accession). Use this when the user asks: list an issuer's insider filings, find a specific accession, filter by form type (Form 4 trades vs Form 3 initial statements vs Form 5 annual vs their /A amendments), count filings over a period, or size a filing (how many transaction / holding rows it has) before pulling detail. This is the filing INDEX. For the actual trades use get_insider_transactions; for the positions use get_insider_holdings. They join on accession_number. Source: SEC bulk Form 3/4/5 dataset (insider_filings_v2), 2006→present, refreshed quarterly. Each row carries the SUBMISSION envelope (company_cik, company_name, ticker, document_type, filing_date, period_of_report, is_amendment), ALL reporting owners (reporting_owners[]), signature rows, and per-table counts (nonderiv_trans_count, deriv_trans_count, nonderiv_holding_count, deriv_holding_count, footnote_count). Useful filter combos: ticker='AAPL', document_type='4' all Apple Form 4 filings company_cik='0000320193', is_amendment=true Apple's amended filings only accession_number='0000320193-26-000078' one specific filing's envelope ticker='TSLA', since='2025-01-01' TSLA insider filings this year ticker='NVDA', reporting_owner_name='Huang' NVDA filings involving Huang document_type values are the raw SEC form codes: '3', '4', '5' and their amendments '3/A', '4/A', '5/A'.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only filings with filing_date >= this date.
untilNoISO date (YYYY-MM-DD). Only filings with filing_date <= this date.
tickerNoExact issuer ticker (e.g., 'AAPL', 'BRK.B').
sort_byNoSort field. Only filing_date is supported. Default: filing_date.
sort_orderNoDefault: desc (most recent filings first).
company_cikNoIssuer CIK (10-digit, leading-zero padded). All of that company's insider filings.
company_nameNoCase-insensitive substring against issuer company name (e.g., 'Apple', 'Tesla').
is_amendmentNoTrue returns only amendments (/A forms); false returns only originals. Omit for both.
document_typeNoExact SEC form code: '3' (initial), '4' (changes), '5' (annual), or amendments '3/A' / '4/A' / '5/A'.
accession_numberNoExact EDGAR accession number — returns that one filing's envelope directly.
reporting_owner_nameNoCase-insensitive substring matched against ANY reporting owner on the filing (scans reporting_owners[]). Best combined with ticker/company_cik.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover only the safety profile (readOnly/destructive/openWorld), but the description goes far beyond: ticker search surfaces retired-symbol rows, rows gain current_ticker, share classes are not merged, retired symbols return only their own rows, plus source (SEC bulk dataset insider_filings_v2), coverage (2006→present), and refresh cadence (quarterly). This is rich behavioral disclosure the annotations cannot supply.

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?

Information-dense with almost no filler, but it front-loads ticker/retired-symbol edge cases before stating the core purpose, which is buried mid-paragraph. A reader has to get past the caveats to learn what the tool returns; a short purpose lead would improve ordering.

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 no output schema and 12 optional parameters, the description compensates by enumerating the returned row fields (company_cik, company_name, ticker, document_type, filing_date, period_of_report, is_amendment, reporting_owners[], signature rows, per-table counts), the data provenance, and the join keys to siblings. 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?

Schema description coverage is 100%, so the per-parameter docs already carry the baseline. The description still adds value with concrete filter-combo recipes (ticker+document_type, company_cik+is_amendment, accession_number alone, ticker+reporting_owner_name) and clarifies that document_type uses raw SEC form codes including /A amendments. It stops short of full combinatorial guidance, but exceeds the 100%-coverage 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?

States a specific verb+resource: 'Returns FILING-LEVEL records from SEC Form 3/4/5 filings — one row per filing (accession).' It explicitly positions itself as the filing INDEX and names the two siblings it is not (get_insider_transactions for trades, get_insider_holdings for positions). An agent can distinguish it from every neighbor 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 Guidelines5/5

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

Provides an explicit when-to-use list ('list an issuer's insider filings, find a specific accession, filter by form type... count filings over a period, or size a filing') and names the alternatives with the join key ('They join on accession_number'). This is textbook when/when-not/alternatives routing.

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

get_insider_holdingsA
Read-only
Inspect

A ticker search also returns rows this issuer FILED UNDER SYMBOLS IT NO LONGER LISTS (renames, filer typos, ADR spellings). Each row keeps ticker as SEC received it and gains current_ticker when the issuer trades under a different symbol today. Separately-listed share classes are NOT merged, and asking for a RETIRED symbol returns only rows filed under it — retired symbols get reissued to other companies. Returns per-security INSIDER POSITIONS from SEC Form 3/4/5 filings — one row per holding line reported by a corporate insider (director, officer, or 10%+ beneficial owner). Use this when the user asks: what a specific insider currently HOLDS, who the largest insider holders of a stock are, an insider's position across companies, or direct-vs-indirect ownership structure. This is the position (stock) companion to get_insider_transactions (the buys/sells flow). Source: SEC bulk Form 3/4/5 dataset (insider_holdings_v2), 2006→present, refreshed quarterly. Each row carries the filing envelope (company_cik, company_name, ticker, reporting_owner_cik/name, role flags, filing_date, period_of_report), the position (holding_type nonderiv|deriv, security_title, shrs_owned_following_trans, valu_owned_following_trans, direct_indirect_ownership D|I), and — for derivative holdings — conv_exercise_price, exercise_date, expiration_date, and underlying-security detail. Useful filter combos: ticker='NVDA', sort_order='desc' most-recent NVDA insider holdings reporting_owner_cik='0001214128' one insider's positions everywhere ticker='AAPL', holding_type='deriv' AAPL insiders' option/RSU positions ticker='TSLA', is_ten_percent_owner=true 10%+ owners of TSLA company_cik='0000320193', min_value=1000000 Apple insiders holding >$1M reporting_owner_name='Musk' name substring (case-insensitive) shares/value are 'following the reported transaction' — the position as of that filing, not a live real-time holding. For the trades themselves use get_insider_transactions; ownership ties together via reporting_owner_cik.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only holdings whose period_of_report >= this date.
untilNoISO date (YYYY-MM-DD). Only holdings whose period_of_report <= this date.
tickerNoExact issuer ticker (e.g., 'AAPL', 'BRK.B').
sort_byNoSort field. Only period_of_report is supported. Default: period_of_report.
min_valueNoMinimum USD value owned following the reported transaction. Use to focus on large positions.
is_officerNoTrue returns only holdings reported by officers.
min_sharesNoMinimum shares owned following the reported transaction. Use to focus on large positions.
sort_orderNoDefault: desc (most recent reporting period first).
company_cikNoIssuer CIK (10-digit, leading-zero padded). Returns insider holdings across all reporting periods for that company.
is_directorNoTrue returns only holdings reported by directors.
company_nameNoCase-insensitive substring against issuer company name (e.g., 'Apple', 'Tesla').
holding_typeNo'nonderiv' = direct securities (common stock); 'deriv' = derivative holdings (options, RSUs, warrants, convertibles). Omit for both.
merge_co_reportsNoDEFAULT TRUE — leave it alone unless you specifically want raw filings. When shares are held through a fund, trust or family holding company, every person deemed a beneficial owner files their own Form 3/4/5 reporting the SAME position, so one block appears once per filer. By default those lines are merged into one row per position, so share counts are the shares actually held; reporting_owner_name names every filer and co_reported_accessions lists every accession. Set false for one row per filing — totals then count the same shares once per reporting person.
reporting_owner_cikNoInsider CIK (10-digit, leading-zero padded). Returns one insider's positions across every company they report on.
is_ten_percent_ownerNoTrue returns only holdings reported by 10%+ beneficial owners.
reporting_owner_nameNoCase-insensitive substring against the insider's name (e.g., 'Musk', 'Cook').
direct_indirect_ownershipNo'D' direct ownership, 'I' indirect (held via trust, LLC, family member, etc.).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/non-destructive, but the description goes well beyond: it discloses that ticker search returns rows filed under retired symbols, that `current_ticker` is added for renamed issuers, that share classes are NOT merged, that retired symbols get reissued, that merge_co_reports defaults to true and merges co-reported positions, and that shares/value are 'following the reported transaction' rather than live. This is exactly the kind of non-obvious behavior 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?

Front-loaded with the most important disambiguation (the retired-symbol and companion-tool notes), and the filter-combo block is scannable. It is dense and somewhat long, with a mild redundancy in naming get_insider_transactions twice, but nearly 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 an 18-parameter, no-output-schema tool, the description is thorough: it describes the source dataset and cadence, the full row structure (filing envelope, position fields, derivative fields), merge behavior, and the position-vs-transaction caveat. 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?

Schema coverage is 100%, so the baseline is 3, but the description adds real value beyond the schema: concrete filter-combo examples with literal values, the note that shares/value reflect the position as of the filing (not real-time), and the ticker-vs-current_ticker distinction. It stops short of full coverage but meaningfully enriches the parameter semantics.

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 ('Returns per-security INSIDER POSITIONS from SEC Form 3/4/5 filings — one row per holding line reported by a corporate insider') and explicitly distinguishes itself from get_insider_transactions as the 'position (stock) companion' versus the buys/sells flow. An agent can route between the two siblings 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?

Explicitly enumerates when to use it: 'what a specific insider currently HOLDS, who the largest insider holders of a stock are, an insider's position across companies, or direct-vs-indirect ownership structure.' Names the alternative (get_insider_transactions) for the trade-flow case and supplies concrete filter combos for common queries.

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

get_insider_transactionsA
Read-only
Inspect

Returns executive insider transactions filed on SEC Form 4 — open-market purchases and sales by officers, directors, and 10%-owners of public companies. Each record is one transaction line item from one filing. Use this when the user asks about: insider buying or selling at a specific company, all recent insider activity across the market, transactions by a specific officer, or large insider trades by value. Form 4 is the fastest insider-trade signal in the public record — must be filed within 2 business days of the trade. The reporting_lag_days field tells you how stale a particular disclosure is. Returns BOTH non-derivative rows (direct common-stock buys/sells, RSU vests, grants, gifts, tax-withholding sales) AND derivative rows (option exercises, warrant conversions, RSU/PSU activity). Filter to one or the other with is_derivative; filter to specific transaction codes with transaction_codes. Common transaction codes: P open-market purchase | S open-market sale A grant / award / RSU vest | M exercise of derivative X exercise of in/at-the-money derivative | C conversion of derivative F payment of exercise price or tax with shares | G bona fide gift D disposition to issuer (forced) | I 401(k)/ESPP | V voluntary ⚠ shares and price_per_share are NULLABLE, and null does not mean zero. SEC permits either to be omitted — the price can live in a footnote, and the share count is genuinely undetermined on instruments that convert at a future price (a convertible note settling on a later VWAP). Those filings state a dollar amount instead, so such rows carry total_value with a null shares. Before 2026-08-18 they were dropped from this dataset entirely. Do not do arithmetic on either field without a null check, and do not read a null share count as a trade of nothing — read total_value. Useful filter combos: ⚠ transaction_codes=['P'] IS NOT 'open-market buys'. SEC defines P as 'open market OR PRIVATE purchase', and the code alone says nothing about whether the security is common stock. Verified 2026-08-14: FLUT's code-P rows are $250M of Total Return Swaps (is_derivative=true) and ATTO's are an $8.5M private placement. Both are correctly labelled in transaction_nature and security_title — but a screen filtered on the code alone ranks them top by size. transaction_codes=['P'], is_derivative=false, include_non_open_market=false genuine open-market common-stock buys — the combination you almost always want transaction_codes=['M','X'] option exercises (cash-out trigger) transaction_codes=['A'] grants / RSU vests is_derivative=true all option/RSU/warrant activity is_derivative=false, transaction_type='sell', min_value=1000000 large open-market sells of common stock Optional include_baseline=true: also returns matching Form 3 initial- ownership records (the insider's starting position when they first became an insider) under a baselines field. Use this when you need to know how big a sale is relative to the insider's full position — Form 4 alone shows the delta, Form 3 anchors the baseline. Requires ticker or company_cik to be set. Baseline rows with is_nil_filing=true are 'no securities owned' Form 3s (~half of all filings) — the insider filed but started with ZERO holdings; shares_owned 0 is the position, not missing data. A ticker search also returns rows this issuer FILED UNDER SYMBOLS IT NO LONGER LISTS — renames, filer typos and ADR spellings all split a company's history across symbols. Each row keeps ticker exactly as SEC received it and gains current_ticker when the issuer trades under a different symbol today; the response carries ticker_resolution naming every symbol searched. Separately-listed share classes are NOT merged: GOOG does not return GOOGL. Asking for a RETIRED symbol returns only rows filed under it, because retired symbols get reissued to other companies. Rows found under a retired symbol are checked against the issuer's CIK, so a symbol another company files under today cannot leak its rows in. Coverage: full history on the bulk leg; the live-feed leg is scanned back 180 days, so a rename in the last few days may not be covered yet. data_source SELECTS WHICH BACKING COLLECTION: 'bulk_v2' (DEFAULT as of 2026-05-24) — insider_transactions_v2 collection populated by SEC quarterly bulk Forms 3/4/5 TSV bundles. Deeper history (2006q1 → latest published quarter, ~9.9M rows). ⚠ RECENCY: the bulk dataset ends at the last PUBLISHED quarter (SEC releases it ~2 weeks after quarter end). On simple recency queries (descending sort, no v2-only filters) filings newer than that boundary are AUTO-MERGED from the live daily feed, so the default view stays current — coverage_warning says when this happened. For post-boundary browsing with v2-only filters, query data_source:'legacy' directly. INLINED FOOTNOTES (footnote_refs[] with resolved text on every row), aff10b5one 10b5-1 plan flag, full reporting_owners array, schema_era. Filters: ticker, company_cik, reporting_owner_cik, reporting_owner_name (substring), row_type ('nonderiv'|'deriv'), trans_codes (aka transaction_codes — either spelling works on either data_source), aff10b5one, schema_era ('pre_2023'|'2023_plus'), since/until, sort_by ('transaction_date'|'filing_date'). PLAUSIBILITY FIELDS — WHAT THEY CAN AND CANNOT CONCLUDE: Every row carries price_check and volume_check, and both are ALWAYS non-null: they say whether each check ran, and why not when it did not. Read those first. ⚠ THE RAW MARKET VALUES ARE PAID-PLAN ONLY. price_range_low and price_range_high (bulk rows), daily_range (legacy and live-feed rows) and shares_vs_daily_volume are Tiingo market data, which KeyVex's licence restricts to paid plans. On other plans those keys are OMITTED — not null — and the response carries licensed_fields_withheld naming them. The verdicts computed from them (price_check, price_outside_daily_range, price_fits_date, volume_check, volume_verdict) are served on every plan. ⚠ THE OTHER THREE ARE OFTEN ABSENT OR NULL, AND THIS TEXT USED TO SAY 'every row carries' ALL FOUR, WHICH WAS FALSE. Measured 2026-09-04 by the KeyVex auditor over a 500-row market-wide March sample: price_outside_daily_range key present 500/500, NON-NULL on 178 volume_verdict key present 500/500, NON-NULL on 178 shares_vs_daily_volume key ABSENT on 500/500 The 322 nulls are exactly the rows where volume_check is not 'checked' — so the reason is always available, on the field that says so. shares_vs_daily_volume is stamped only alongside a NON-NORMAL volume verdict, and the same sample contained no non-normal rows, so an ordinary response carries it nowhere. Do not build on its presence. A null here means NOT CHECKED. It never means fine. They were served without definition until 2026-09-01, which is how 'impossible' came to read as a stronger claim than the check supports. volume_verdict compares REPORTED SHARES against that day's recorded volume, and shares_vs_daily_volume is the raw ratio so you can judge for yourself: 'normal' ratio <= 0.25 'outsized' ratio > 0.25 — a large share of the day's tape 'impossible' ratio > 1 — MORE SHARES THAN THE DAY RECORDED. ⚠ 'impossible' means the two numbers cannot both be right, NOT that the trade did not happen. Our volume is one daily bar: it need not include off-exchange or block prints, and a Form 4 may report several days' activity on one date. Treat it as strong evidence of a reporting or data problem worth investigating, not as proof the transaction is fake. null = not judged. Computed only for market claims (codes P and S) — a grant never touched the tape, so a ratio on it would be noise. price_check says whether the price was tested against that day's bar: 'checked' tested; price_outside_daily_range holds the result 'misdated' tested; the price is OUTSIDE that day's bar (see daily_range) — price_outside_daily_range is TRUE — but fits the bar of price_fits_date, within 3 calendar days. Read as: a real fill whose filer wrote the wrong date. KeyVex's own screens treat it as real: its dollar total is kept, it is not vetoed as non-open-market, and co-report resolution never drops it silently. 'no_price_reported' the filer stated no price 'no_positive_price' the filer stated a price of zero or less, so there was nothing to compare. The bar may be present — see volume_check. 'no_verdict_recorded' the day's bar was found (volume_check ran off it) but its high/low were unusable, so the price half is unjudged 'no_daily_bar' no usable bar for that ticker and date ⚠ THE LAST THREE ARE DELIBERATELY DISTINCT. Until 2026-09-04 all three were served as 'no_daily_bar', which asserted a missing bar on rows whose shares_vs_daily_volume — a ratio computable only FROM that day's bar — was served three fields away. Found live by the trading simulation. If you match on 'no_daily_bar', match on all four. volume_check says whether the SHARES-vs-VOLUME check ran, and is now independent of the price half: 'checked' | 'not_a_market_trade' | 'no_daily_bar'. A row can be volume_check 'checked' while price_check is 'no_positive_price' — the bar was there, only the price was not. price_outside_daily_range is true|false|null, and NULL MEANS NOT CHECKED — never 'fine'. A row whose price_check is any value other than 'checked' or 'misdated' has not been vetted on price at all, so do not read its silence as a pass. CLUSTER BUY (every data_source): cluster_buy_insiders_30d = the number of DISTINCT reporting owners (by CIK) with an open-market purchase (code P) in the same ticker in the 30 days ending on this row's transaction_date, this row included; cluster_buy = a code-P row with that count >= 3. Both are NULL — never a guess — on a row that is not a purchase, or when the window cannot be counted; cluster_buy_basis always says which, e.g. 'owner CIK not recorded for trades before 2026-07-01' (live-feed rows before then carry no owner CIK; bulk rows always do). BACKWARD-COMPAT: every v2 row also carries the LEGACY field aliases (disclosure_date, transaction_code, shares, price_per_share, total_value, acquired_disposed, shares_owned_after, officer_name, is_derivative, reporting_lag_days, data_source, sec_filing_url) so callers reading the old field names keep working. The transaction_type field carries the legacy 'buy'|'sell' semantic (synthesized from trans_code + trans_acquired_disp_cd, identical algorithm to the legacy scraper); the v2 nonderiv|deriv discriminator lives at row_type. 'legacy' — insider_trades collection populated by KeyVex's daily EDGAR scraper. Shallower coverage (2022+), no footnotes, no aff10b5one, ~91% fewer filings in the same window than bulk_v2. Rows written since 2026-09-30 also carry reporting_owner_cik (the filing's FIRST reporting owner, 10-digit, the bulk's own rule) and reporting_owner_ciks (every owner on the filing); older legacy rows do not, so the field's absence means 'not recorded', not 'none'. Filters: ticker, company_cik, officer_name, transaction_type (buy|sell), is_derivative, transaction_codes (aka trans_codes), min_value, since/until, sort_by (disclosure_date|transaction_date|total_value). Use this only when you specifically need the legacy doc shape with NO v2-extension fields. SEC-SOURCE DATE CONVENTIONS — read raw values with these in mind: KeyVex preserves SEC's authoritative bytes exactly as published. Two recurring source-data patterns are worth recognizing so agents interpret raw date values correctly: (1) PERPETUAL-INSTRUMENT SENTINEL — exercise_date or expiration_date values of 2050-12-31 / 2050-08-31 ARE SEC's established convention for instruments with no calendar expiration (Deferred Stock Units, certain Non-Qualified Stock Options, Units of Limited Partnership Interest, similar perpetual or condition-vested derivatives). Read these as 'no expiration,' not as literal calendar dates in 2050. This is a fact about SEC's schema, not an inference. (2) ANOMALOUS-YEAR FILER-ENTRY PATTERN — date values with out-of-range year components — e.g., 0012-11-21 or 0025-07-25 (likely 2-digit years entered into a 4-digit field), or 2027-01-25 on a 2026 filing / 2028-03-19 on a 2024 filing (likely single-digit transpositions) — appear to be filer data-entry typos preserved verbatim from SEC's primary filings. KeyVex verified on a stratified spot-check that these values are byte-identical between SEC's primary XML and SEC's bulk extract (22 / 22 matches across all observed pattern faces); the SEC-to-KeyVex transit is faithful. The pattern is ongoing — observed across filings from 2014 through 2026, not legacy-only. Cross-reference filing_date to infer the likely intended year. (3) NUMERIC PRECISION — for data_source='bulk_v2', shares and price_per_share mirror SEC's BULK Form 345 extract, which rounds to 2 decimals (e.g. 474.6, where the primary XML shows 474.598). That rounding is SEC's, in the bulk feed — KeyVex stores the bulk value verbatim (no rounding in the loader). Audit v2 numerics against the bulk extract (the source of record), not the XML primary document, which carries fuller precision. Dates and transaction codes DO match the XML exactly. (4) A DISCLOSURE DATE IS NOT CLOSED WHEN THE DAY ENDS. Filings keep arriving bearing a disclosure_date that has already passed, because SEC accepts them late and there is no cut-off after which a date stops gaining rows. So the SAME disclosure_date window can return MORE rows tomorrow than it did today, and a result cached against that date goes quietly stale — the count does not change, so nothing looks wrong. Observed 2026-08-14: the newest disclosure_date on the tape was still 2026-08-13, yet a row bearing 08-13 was first ingested at 07:01 ET the NEXT morning. A caller working from the previous afternoon's view of 08-13 missed $1.26M of buying in a position it already held. (5) SANITY-CHECK A BIG DOLLAR FIGURE AGAINST VOLUME, IN THIS API. total_value is derived (shares x price) wherever SEC did not file a total, so a filer's unit or decimal slip lands in it. The cheapest test is whether that many shares could plausibly have traded: get_daily_prices(ticker, since, until, include_ohlc=true) -> volume Compare the reported share count to the session's volume. A purchase that is a large multiple of everything that traded is worth a second look before acting on it. Verified examples, 2026-08-14: COE reported 592,320 ordinary shares against 52,418 ADS traded — a 60:1 ADS ratio, not a real $11.8M buy. EVGN reported 460,000 against 326,793 traded (141%) and was FINE — Evogene is dual-listed on NASDAQ and Tel Aviv, so the US tape sees only part of the volume. The check flags what to examine; it does not decide. Both readings beat ranking by total_value and trusting the top. RE-QUERY rather than reusing a prior window. 'Same disclosure date' does not mean 'same rows'. If you need to detect what is NEW since your last look, compare against the row identity you saw before rather than assuming a closed date is settled — and note that a sync timestamp moving is a statement about the JOB, not about the DATA. Pure-publisher posture: KeyVex mirrors SEC's exact bytes, documents these conventions and filer quirks rather than altering them, and never silently 'corrects' a value to KeyVex's guess of what was meant. A customer auditing KeyVex against EDGAR's source of record for each row (the bulk Form 345 extract for v2 rows) will find a byte-for-byte match. MACHINE-READABLE FLAGS — responses include a source_metadata block on rows where the above SEC-source patterns are detected. The block is keyed by field name, with an array of flag strings per field: sec_perpetual_sentinel (assertive — exact-string match on a known SEC sentinel value); anomalous_year_likely_filer_entry (calibrated — year outside the plausible range on transaction_date, exercise_date, expiration_date, or period_of_report; covers filing-pipeline data quality issues across the upstream-actor stack including filer typos, filing-agent default-epoch substitutions, and other cause-classes where the year falls outside any plausible range). Presence is the signal: clean rows have NO source_metadata field at all (not an empty object — the field is omitted entirely). Absence means 'no SEC source quirks detected,' NOT 'certified clean by audit' — agents weigh the difference. The raw source date values are preserved unchanged; the flag block carries KeyVex's labeled interpretation alongside, never replacing.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
cursorNoOpaque pagination cursor. To read past `limit`, pass the `next_cursor` value from the previous response VERBATIM; the response omits next_cursor when there is nothing after this page. Keyset-based, not offset-based: the cursor names a position in the sort order, so filings that arrive while you page do not shift or duplicate rows beneath you. Works on BOTH data sources (bulk_v2 since 2026-08-08) — on bulk_v2 it names a position in the MERGED bulk + live-daily-feed stream, and both legs are advanced together. Keep sort_by/sort_order identical across a page sequence — a cursor issued under a different sort is REJECTED rather than silently applied to the wrong ordering. (`offset` and `page` are not supported and are rejected: an offset into this result is not an offset into either underlying source, and on the legacy store it would bill for every row it skipped.)
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive.
sort_byNoField used for ordering and for the since/until date filters. Default: disclosure_date. Validity differs by data_source: 'transaction_date' works on BOTH; 'disclosure_date' works on both (on the default bulk_v2 it maps to filing_date); 'total_value' is LEGACY-ONLY — bulk_v2 rejects it, so to rank by trade size on bulk_v2 use min_amount to filter and sort by transaction_date instead.
row_typeNobulk_v2 only. Source-table discriminator: 'nonderiv' for NONDERIV_TRANS rows (direct common-stock activity), 'deriv' for DERIV_TRANS rows (options/RSUs/warrants). For legacy data, use is_derivative instead.
min_valueNoFilter to trades with total_value >= this amount (USD). Use to focus on large trades. Works on BOTH data_sources. On bulk_v2 the value is DERIVED per row exactly as the returned `total_value` field is — TRANS_TOTAL_VALUE where the SEC populated it (derivative rows), otherwise shares × price_per_share — so the filter and the field always agree. Rows carrying neither (no value and no shares/price) are EXCLUDED, since an unknown value cannot be shown to clear the threshold; that matches legacy — pass include_unpriced=true to keep them, and the response carries `min_value_note` saying so whenever min_value is set. Note this is a post-fetch filter on bulk_v2, so a very high threshold may return fewer rows than `limit` with has_more=true.
aff10b5oneNobulk_v2 only. 10b5-1 trading-plan flag. '1' = plan adopted, '0' = no plan, '' = filer left the box blank (most common in 2023q1+ era), 'NOT_TRACKED' = pre-2023 era where the column did not exist on the SEC form. Filers often leave the box blank but disclose the plan in narrative footnotes — check footnote_refs[] for trans_code annotations.
schema_eraNobulk_v2 only. Form-version era. 'pre_2023' = filings made 2006q1 through 2022q4 (no AFF10B5ONE column). '2023_plus' = filings made 2023q1 onward (AFF10B5ONE column present, matches SEC Rule 10b5-1 amendment compliance date). Driven by FILING-quarter, not transaction_date — a late 2024 filing of an old 2009 trade still gets schema_era=2023_plus.
sort_orderNoDefault: desc (most recent / largest first).
company_cikNoSEC CIK number (10-digit, padded with leading zeros). Alternative to ticker when known.
data_sourceNoWhich backing collection to query. 'bulk_v2' (DEFAULT as of 2026-05-24) = SEC quarterly bulk dataset, 2006q1 → the last PUBLISHED SEC quarter (SEC releases it ~2 weeks after quarter end; the live boundary is stated in coverage_warning). Footnote_refs[] inlined, aff10b5one present, full reporting_owners array, deeper coverage. Rows carry legacy field aliases for backward compat. On simple recency queries (descending, no v2-only filters) filings NEWER than the bulk boundary are automatically merged in from the live daily feed, so the default view stays current. 'legacy' = daily EDGAR scraper output (insider_trades collection, no footnotes, no 10b5-1 flag). Its history runs from 2016 but is NOT continuous: measured 2026-08-10 against SEC's own bulk copy, legacy holds ~2.1% of 2022, ~0.3% of 2023 and ~4.4% of 2025, and is complete for 2016-2021, 2024 and 2026. Those are gaps in the scraper's history, not in SEC's data, and responses covering them carry a coverage_warning. (An earlier version of this description said '2022+ only', which was the inverse of the truth.) Use 'legacy' ONLY when you specifically need the legacy document shape, or to browse post-boundary filings with filters the auto-merge can't map. bulk_v2 (the default) is authoritative for coverage.
trans_codesNoOR-filter on raw SEC trans_code values (P, S, A, M, X, C, F, G, D, I, V, etc.). The v2 spelling of `transaction_codes` — same semantics, same codes; either spelling is accepted on either data_source and passing both with different values is rejected. Max 30 codes.
officer_nameNoFull or partial officer name; case-insensitive substring match. Works on BOTH data_sources — `reporting_owner_name` is the same filter under its v2 name, and either spelling is accepted on either source; passing both with different values is rejected.
is_derivativeNoFilter to derivative rows (options, RSUs, warrants, convertibles) when true, or non-derivative common-stock rows when false. Omit to see both. Works on BOTH data_sources — on bulk_v2 it maps to row_type ('deriv'/'nonderiv'); passing is_derivative and a conflicting row_type is rejected.
include_baselineNoWhen true, the response includes matching Form 3 initial-ownership records under a `baselines` field — lets you anchor Form 4 deltas to the insider's starting position. Requires ticker or company_cik. Default false. Works on BOTH data_sources (bulk_v2 accepted-but-ignored it until 2026-08-05).
include_unpricedNoOnly meaningful alongside min_value. By default a row that states NO price (price_check='no_price_reported') has no derivable total_value, cannot be shown to clear the threshold, and is EXCLUDED — correct, but it used to be silent, and 'cannot be shown to clear the threshold' is not 'is below the threshold'. Measured 2026-09-09 at roughly 3 rows in 10,000, every one a filing where the insider genuinely stated no price rather than a data defect. Pass true to keep those rows in a min_value-filtered result; their total_value is null, so judge them on shares. Default false, which is exactly today's behaviour. bulk_v2 only: passing it with data_source='legacy' is REJECTED rather than ignored, because a filter flag that silently does nothing is worse than one that is unavailable. Passing it without min_value is also rejected, for the same reason — nothing would be being excluded for it to re-admit.
merge_co_reportsNoDEFAULT TRUE — leave it alone unless you specifically want raw filings. When shares are held through a fund, SEC requires the holding entity, its general partner AND the individual with investment control to each file their own Form 4 for the SAME purchase. By default those filings are merged into one row, so share counts and dollar totals are what actually traded; the row's officer_name names every filer and co_reported_accessions lists every accession. Set false to get one row per filing instead — useful for filing-level audit, but totals then double-count the transaction once per reporting person.
transaction_typeNoFilter by direction. 'buy' means PURCHASED, not merely acquired: setting this parameter also switches include_non_open_market to false by default, so RSU vests, option exercises and other grants (transaction_nature=EQUITY_COMP) and gifts/transfers/equity swaps (NON_OPEN_MARKET_TRANSFER) are EXCLUDED. Without that default a 'buy' screen is mostly vesting schedules — measured 2026-08-11 at 83% EQUITY_COMP, with a $6.3bn nano-cap grant topping the dollar-sorted results. ⚠ include_non_open_market=true does NOT widen a direction-filtered query, and this description used to say it did ('pass it to get the full ACQUIRED superset, grants included') — corrected 2026-08-27 after the promise was measured against the behaviour. A direction is only ASSERTED for a genuine market trade: since 2026-08-17 the field is null for anything whose transaction_nature is not OPEN_MARKET, and for derivatives, because equity compensation is not buying (a Kyndryl new-hire grant had been ranking as $5.2M of insider buying at a discount to the market price). A row with no direction cannot match transaction_type=buy whatever include_non_open_market says. To see grants and transfers, OMIT transaction_type and filter on transaction_nature yourself — include_non_open_market widens exactly as documented there. Rows whose nature cannot be classified (INSUFFICIENT_DATA) always pass through where no direction filter is set, and are counted in unclassifiable_records_retained — unclassified is not the same as excluded. Works on BOTH data_sources. For legacy, this filters the stored field directly. For bulk_v2 (default), the field is derived per row from trans_code + trans_acquired_disp_cd (P→buy, S→sell, acqDisp=A→buy, acqDisp=D→sell, fallback A/M/X/C/I→buy else sell — same algorithm legacy uses); the v2 path pages through Firestore until enough matches are found and reports has_more accurately on the filtered set.
transaction_codesNoOR-filter on raw SEC transaction codes. Common picks: ['P'] open-market buys; ['S','F'] sells + tax-withholding; ['M','X'] option exercises; ['A'] grants/RSU vests; ['G'] gifts. Max 30 codes. Works on BOTH data_sources — `trans_codes` is the same filter under its v2 name, and either spelling is accepted on either source; passing both with different values is rejected.
reporting_owner_cikNoReporting owner CIK (10-digit, zero-padded). bulk_v2 only — legacy uses officer_name substring instead.
reporting_owner_nameNoReporting owner name substring (case-insensitive). bulk_v2 only — legacy uses officer_name instead. IMPORTANT: name is matched client-side over a recent window, so it must be ANCHORED by ticker, company_cik, or reporting_owner_cik to search the full history — a name on its own only scans the most recent filings and can miss older trades (the response carries a coverage_warning when used unanchored).
include_non_open_marketNoPhase A v0.52.0 (2026-05-24): controls whether NON-MARKET events appear in the result. When false (the honest default for direction queries), the result keeps ONLY OPEN_MARKET rows (transaction_nature='OPEN_MARKET') plus INSUFFICIENT_DATA rows (passthrough — unclassified is not the same as confirmed-non-market, never silently dropped). It excludes BOTH NON_OPEN_MARKET_TRANSFER (gifts G, tax-withhold F, disposition-to-issuer D, will/inheritance W, voting-trust Z, tender U) AND EQUITY_COMP (grants A, exercises M/X/O, 401k/ESPP I, conversions C) — neither is a true open-market trade. Honest-by-default: when transaction_type='buy'|'sell' is set, defaults to FALSE; pass true to opt back in and see all natures. When transaction_type is NOT set, defaults to TRUE (returns everything, honestly tagged); pass false for a clean OPEN_MARKET+INSUFFICIENT_DATA view. The transaction_type field on each row is never mutated by this filter. The response envelope carries `unclassifiable_records_retained: N` when any INSUFFICIENT_DATA rows passed through, so the caller knows N of the returned rows couldn't be classified.

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description goes well beyond that, disclosing coverage boundaries, license-withheld fields, nullable-value traps, and recency auto-merge behaviour — but much of this is framed as historical corrections ('this text used to say... which was false'), which reads as an audit changelog rather than invocation-relevant behaviour. Substantive transparency is high, but the signal-to-noise is diluted.

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

Conciseness2/5

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

Purpose is front-loaded, but the body runs to many screen-lengths and is heavily padded with version-dated changelog entries, audit measurements and self-corrections ('measured 2026-09-04 by the KeyVex auditor...', 'this text used to say...'). For an agent selecting and calling a tool, the vast majority of this text does not change behaviour and crowds out the operative guidance.

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 24-parameter, zero-required, no-output-schema tool spanning two backing datasets, the definition covers selection, filtering, null semantics, pagination and source-of-truth caveats. Nothing an agent needs in order to call it correctly is missing, even if it is delivered verbosely.

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 the baseline is 3, and the schema already documents every filter thoroughly. The description earns above baseline by adding meaning the schema cannot: the P-is-not-open-market trap with named counterexamples, the interaction between transaction_type and include_non_open_market, and the min_value/include_unpriced coupling.

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 ('Returns executive insider transactions filed on SEC Form 4') and immediately narrows scope to open-market purchases and sales by officers, directors and 10%-owners. It further distinguishes itself from sibling insider tools by naming the row granularity ('one transaction line item from one filing') and the derivative/non-derivative split.

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?

Explicit 'Use this when the user asks about' enumeration covers the main intents, and the 'Useful filter combos' block names the exact parameter sets to run per intent. The data_source section states when to prefer 'legacy' versus the default 'bulk_v2', including the exclusion condition ('only when you specifically need the legacy doc shape').

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

get_institutional_holdingsA
Read-only
Inspect

Returns 13F holdings — quarterly snapshots of equity positions held by institutional investment managers with $100M+ AUM, filed with the SEC. Each record is one (fund, security, quarter) tuple. Use this when the user asks about: which institutions hold a stock, a fund's portfolio, position changes quarter-over-quarter, or 'whale' activity in a specific name. Reporting lag: up to 45 days after quarter end. A 2026-Q1 filing typically appears in mid-May 2026. The most recent quarter visible always lags real time. Important: 13F covers institutional managers ≥ $100M AUM but does NOT include short positions, cash, options (with rare exceptions), or non-US-listed equities. It's a snapshot of long equity positions only. For 'did the fund increase its AAPL stake?' questions, check the position_change field — values are 'new', 'increased', 'decreased', 'closed', or 'unchanged' relative to the same fund's prior quarter.

ParametersJSON Schema
NameRequiredDescriptionDefault
cusipNoAlternative to ticker — 9-character SEC CUSIP identifier. Useful when a security has multiple share classes with different tickers.
limitNoMaximum records to return. Default 50, max 500.
cursorNoPass the `next_cursor` from the previous response VERBATIM to fetch the next page. Keep every other filter and the sort identical while paging. Omit to start from the top. A quarter of 13F filings runs to far more than 500 rows, so a complete picture requires paging.
tickerNoFilter to holdings of one stock by US ticker, e.g. 'AAPL'. Case-insensitive.
quarterNoPeriod ending date in YYYY-MM-DD form (e.g. '2026-03-31'). Defaults to all quarters available in the database.
sort_byNoField used for ordering. Default: market_value (largest positions first).
fund_cikNoSEC CIK of the fund (10-digit, padded). Preferred over fund_name when known. Berkshire Hathaway = '0001067983'.
fund_nameNoFull or partial fund name; case-insensitive substring match. Examples: 'Berkshire', 'Bridgewater', 'Citadel'.
min_valueNoFilter to positions with market_value >= this amount (USD). Use to focus on large positions.
sort_orderNoDefault: desc (largest first).
position_changeNoFilter to position-change type. Common queries: 'increased' for funds adding to a position, 'closed' for funds that exited.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only cover safety (readOnly, non-destructive, openWorld), so the description adds the operationally decisive facts: a reporting lag of up to 45 days, the fact that the latest visible quarter always trails real time, and that the data is a long-equity snapshot with no shorts/cash/options. It also explains position_change is computed against the same fund's prior quarter, which prevents misreading a field.

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 definition, then usage triggers, then caveats, then field semantics — a sensible order with no wasted preamble. Slightly long, and enumerating the position_change values duplicates the enum in the schema, which is the only real 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?

For an 11-parameter tool with no output schema and no required parameters, the description covers the domain, the temporal caveat, and the grain of each record well. Field-level return detail is thin — only position_change is characterized — so an agent still lacks a full picture of what columns come back, but nothing needed 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.

Parameters4/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 and the schema already carries format details for cusip, quarter, cursor, and the enums. The description still adds real meaning beyond the schema by explaining what position_change values signify ('relative to the same fund's prior quarter') and why quarter choice is constrained by filing lag.

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 ('Returns 13F holdings — quarterly snapshots of equity positions held by institutional investment managers with $100M+ AUM') and defines the record grain as a (fund, security, quarter) tuple. The AUM threshold and 13F framing implicitly separate it from sibling datasets like get_fund_holdings (N-PORT mutual funds) and get_activist_stakes (13D/13G), so an agent can route 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 an explicit trigger list: 'which institutions hold a stock, a fund's portfolio, position changes quarter-over-quarter, or whale activity in a specific name.' It also bounds the domain by listing what 13F excludes (shorts, cash, options, non-US equities), which steers the agent away from wrong questions. No sibling tool is named as an alternative for overlapping cases, so it stops short of full when-not guidance.

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

get_intraday_quoteA
Read-only
Inspect

Returns the latest intraday price for ONE US-listed ticker — a live passthrough to Tiingo's IEX feed, nothing cached. PAID PLANS ONLY. Use this when the question is 'what is X trading at now'. For price HISTORY (daily closes, splits, dividends) use get_daily_prices. Returns: price, and as_of — the exact timestamp of that quote, verbatim from the source. ALWAYS read as_of rather than assuming the quote is current: outside US market hours the feed returns the most recent session's final print, so a quote at 21:00 ET is a 16:00 ET price and as_of is how you can tell. price_field names the source field the price came from (tngoLast / last / mid) so a decision made on it can be re-derived later. A symbol the feed does not cover returns result: null with not_found_reason — never a substituted or stale price. Two reasons are possible: 'no_quote_for_ticker' (unknown symbol, or no quote available) and 'delisted_no_longer_trading' (the security stopped trading; the response carries delisted_since, the day after its last real trade). The second exists because the upstream feed keeps synthesising a current-session row for some delisted names — a flat zero-volume bar at the last real price, stamped with today's close — and a dead security has no current price to report. ⚠ VENUE COVERAGE IS IEX ONLY, and price is Tiingo's tngoLast derived from that feed — not a consolidated-tape print. This matters most on THINLY TRADED names: IEX is one venue carrying a few percent of US volume, so a symbol can go 20+ minutes mid-session without IEX seeing a trade. When that happens as_of legitimately reads stale DURING market hours. It means 'IEX has not seen an update', NOT 'the stock is not trading' — measured 2026-09-09, BWFG sat at a 22-minute-old as_of while trading normally. Do not treat a stale as_of on a thin name as a fault. Three fields let you judge that for yourself rather than trusting a verdict this tool does not make. iex_session_volume is the session volume ON IEX ONLY — it is NOT consolidated volume and is typically a small fraction of it, so never compare it against share counts from other endpoints. prev_close is the prior session's close. And flat_session is true when all four OHLC legs equal the price AND volume is zero AND the price equals prev_close — the shape the feed manufactures for a security that no longer trades. It is a SHAPE, not a delisting verdict: stable-NAV money market funds hold a constant price by design and look identical. It is NULL when the test was impossible — a missing OHLC leg or an unreported volume — and null means 'could not test', never 'false'. One call = one ticker, by licence — there is no multi-ticker parameter. Close Prices from Tiingo.com.

ParametersJSON Schema
NameRequiredDescriptionDefault
tickerYesTicker symbol, e.g. 'AAPL', 'SPY', 'BRK-B' (hyphen for share classes).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover the read-only safety profile; the description adds far more: IEX-only venue coverage with a thin-name staleness caveat and a concrete example, the fact that out-of-hours quotes are the prior session's final print, delisting row synthesis upstream, and the semantics of null (flat_session null = 'could not test', not false). This is exactly the behavioral context annotations cannot carry.

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, paid-plan constraint and the sibling alternative are front-loaded in the first three sentences, which is the right ordering. It is long, but the length is largely earned by genuinely non-obvious caveats (stale as_of, flat_session null semantics, IEX-only volume); a few passages restate the same point in different 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?

With no output schema, the description carries the full return-value burden and does so thoroughly: price, as_of, price_field, iex_session_volume, prev_close, flat_session, and the two not_found_reason values with their meaning. Nothing an agent needs to interpret the response 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% for the single ticker param, so the baseline is 3. The description adds value beyond the schema by stating there is no multi-ticker parameter by licence, which prevents an agent from attempting batching.

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 ('Returns the latest intraday price for ONE US-listed ticker') and pins the scope with 'a live passthrough to Tiingo's IEX feed, nothing cached.' It explicitly contrasts itself with the sibling get_daily_prices for historical data, so an agent can route correctly 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?

Names the exact question this answers ('what is X trading at now') and routes the alternative case ('For price HISTORY ... use get_daily_prices'). It also states a hard eligibility constraint (PAID PLANS ONLY) and the licence constraint of one ticker per call.

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

get_investment_advisersA
Read-only
Inspect

Returns SEC Form ADV registry records — every SEC-registered investment adviser (~17K RIAs) and exempt reporting adviser (~6.5K ERAs, mostly private-fund advisers), from the SEC's monthly roster extract. One record per firm (CRD number) with regulatory AUM (discretionary / non-discretionary / total, Item 5F), employees and IA reps, client counts, custody flags (Item 9A), and disciplinary disclosure flags (Item 11, verbatim sub-question codes). Use this when the user asks: who advises/manages money, how big is an adviser, largest RIAs by state, advisers with disciplinary history, or to vet a firm before pairing with enforcement / holdings data. firm_type: 'registered' RIAs report regulatory AUM; 'exempt_reporting' ERAs do NOT report Item 5F — their AUM fields are null by construction (they report private-fund data instead; see adviserinfo_url for Section 7.B detail). Registry posture: this is a CURRENT-ROSTER snapshot refreshed monthly, not an event history. snapshot_month is the last month the firm appeared — a stale snapshot_month means the firm dropped off the roster (deregistered). min_aum filters on total regulatory AUM and requires the default aum_total sort. CIK is the join key to EDGAR datasets (13F institutional holdings, enforcement). v1A maps a curated ~30-field subset of Form ADV Part 1A's 448-column grid; adviserinfo_url links the firm's full IAPD page. Pure-publisher posture: the SEC's roster as published. A disciplinary FLAG is a disclosure, not a verdict — agents read the detail on IAPD.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoExact EDGAR CIK (any zero-padding) — the join key to 13F / enforcement data.
crdNoDirect lookup by firm CRD number (e.g., '38').
limitNoMaximum firms to return. Default 50, max 500.
stateNoTwo-letter main-office state code (e.g., 'NY').
countryNoMain-office country, verbatim (e.g., 'United States').
min_aumNoMinimum total regulatory AUM in dollars (registered firms only; requires sort_by aum_total).
sort_byNoDefault aum_total (largest first).
firm_nameNoCase-insensitive substring against primary business or legal name.
firm_typeNo'registered' = SEC-registered RIAs (report AUM); 'exempt_reporting' = ERAs (AUM fields null).
sort_orderNoDefault desc.
has_disciplinary_disclosuresNoFilter to firms with (true) / without (false) Item 11 disclosures.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover safety (readOnly, non-destructive, openWorld), and the description adds substantial context beyond them: it is a CURRENT-ROSTER monthly snapshot not an event history, a stale snapshot_month means deregistration, ERA AUM is null by construction, and a disciplinary FLAG is a disclosure not a verdict. This is exactly the kind of behavioral disclosure the structured fields cannot carry.

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?

Long but front-loaded and information-dense, with the core purpose in the first sentence and caveats after. Some redundancy exists (firm_type registered/ERA AUM semantics are stated in both the schema description and the prose), which slightly dilutes 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 an 11-param dataset tool with no output schema, the description is complete: it enumerates returned fields (AUM, employees, client counts, custody flags, Item 11 codes), explains the v1A subset and adviserinfo_url, and clarifies roster/publisher posture. An agent has everything needed to call and interpret results.

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 baseline is 3, but the description adds real meaning: min_aum 'requires the default aum_total sort', firm_type drives whether Item 5F AUM is populated, and CIK is the join key to 13F/enforcement. It goes beyond the schema on the keys an agent must reason about jointly.

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: 'Returns SEC Form ADV registry records' and quantifies scope (~17K RIAs, ~6.5K ERAs). It distinguishes the two firm types and names the record granularity (one per CRD), so an agent can tell it apart from siblings like get_enforcement_actions.

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?

Explicit when-to-use: 'Use this when the user asks: who advises/manages money, how big is an adviser, largest RIAs by state, advisers with disciplinary history, or to vet a firm before pairing with enforcement / holdings data.' It names the alternative sibling datasets (enforcement, holdings) and the conjunction condition.

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

get_lobbying_filingsA
Read-only
Inspect

Returns Lobbying Disclosure Act (LDA) filings — quarterly LD-2 reports filed by registered lobbyist firms with the Senate Office of Public Records. Each record covers one (registrant, client, quarter) tuple, listing income paid, issues lobbied on, and government entities contacted. Use this when the user asks about: who's paying lobbyists, what issues a company is lobbying on, which senators or agencies a firm is contacting, lobbying spend by industry or sector, or to cross lobbying activity against congressional trades or federal contracts for political-influence analysis. Each filing has a lobbying_activities array (one entry per issue area worked on) plus three flattened summary arrays at top level: - general_issue_codes: 3-char codes (DEF, HEA, TRA, ENV, FIN, ...) - government_entities: agencies/branches contacted - lobbyist_names: lobbyists who worked the issue Top-level arrays support indexed queries; the nested array carries issue-level descriptions and lobbyist position info. general_issue_codes filter is OR-semantic — pass an array, match any filing containing AT LEAST ONE of those codes (max 30, per Firestore array-contains-any). Examples: ['DEF'] for defense, ['HEA','MMM'] for health + Medicare/Medicaid, ['TAX','FIN'] for tax + financial services. Income vs expenses (IMPORTANT for ranking by spend): the LDA mandates a hard split. Third-party lobbying firms report income (what the client paid them); in-house corporate lobbying departments report expenses (what they spent). The two fields are mutually exclusive — any given filing has one or the other, not both. In practice ~30% of filings have income, ~70% have expenses, with a small population reporting neither (administrative registrations). So sort_by=income ranks the third-party-firm subset; for an actual top-spenders leaderboard, agents should fetch both populations and sum income + expenses per filing client-side. v1.1 polish will add a derived total_lobbying_spend field that does this sum server-side for indexed queries. client_is_government is true when the client is a government body (US states often hire lobbyists). Activity descriptions are truncated at 5000 chars during ingestion to stay under Firestore's per-doc cap; agents can fetch the full filing via filing_document_url for the unbounded prose.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
sort_byNoField used for ordering and for since/until filters. Default: dt_posted (when the filing was submitted).
min_incomeNoFilter to filings with income >= this amount (USD). Use to focus on big-dollar lobbying spend.
sort_orderNoDefault: desc (most recent / largest first).
client_nameNoSubstring match against the paying client's name (case-insensitive). E.g., 'Pfizer', 'Lockheed Martin', 'STATE OF CALIFORNIA'.
filing_yearNoCalendar year of the reporting period (NOT the filing date).
filing_periodNoReporting period within filing_year. Quarters for LD-2; mid_year/year_end for LD-203 contributions windows.
registrant_nameNoSubstring match against the lobbying firm's name (case-insensitive). E.g., 'Akin Gump', 'Brownstein'.
government_entityNoSubstring match against any government entity contacted. E.g., 'SENATE', 'Treasury', 'FDA', 'Defense, Dept of'.
general_issue_codesNoArray of 3-char issue codes (OR semantics). E.g., ['DEF'] for defense, ['HEA','MMM'] for health+Medicare. Max 30 codes per query.

TDQS

A4.4/5.0
Behavior5/5

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

With annotations covering readOnly, openWorld, and destructive=false, the description adds substantial behavioral context: the income vs expenses split, the ~30%/70% population skew, client_is_government semantics, and the 5000-character truncation with filing_document_url for full prose. It also notes a future derived field, giving agents a clear picture of current limitations and expected data shape.

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 the core purpose and record structure, then moves to use cases and caveats in a logical order. It is long but mostly earns its length given the complex 12-parameter tool with no output schema, though the v1.1 roadmap note and some repetition could be trimmed.

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?

There is no output schema, so the description carries the burden of explaining return values, which it does thoroughly: it describes the lobbying_activities array, three flattened summary arrays, income vs expenses fields, truncation, and the full-document fallback. Combined with the schema and annotations, an agent has enough information to invoke and interpret the tool 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 description coverage is 100%, so the baseline is 3. The description adds some meaning for general_issue_codes OR semantics and sort_by=income, but those details are largely already present in the schema, and most other parameters are documented only 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?

The description states a specific verb and resource — returns Lobbying Disclosure Act (LDA) filings — and defines the record grain as one (registrant, client, quarter) tuple with income, issues, and entities. It clearly differentiates from related sibling tools like get_lobbyist_contributions by focusing on quarterly LD-2 filings rather than campaign contributions.

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 explicit usage scenarios: who's paying lobbyists, issues a company is lobbying on, senators/agencies contacted, lobbying spend by industry, and cross-referencing against congressional trades or federal contracts. It does not name alternative tools or state when not to use this tool, so it falls short of the top score.

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

get_lobbyist_contributionsA
Read-only
Inspect

Returns LD-203 semiannual contribution reports — what registered lobbyists and lobbying firms themselves contribute: FECA campaign contributions, honorary expenses, event/meeting costs, and presidential-library / inaugural-committee donations, each item naming the HONOREE (the covered official who benefited). This is the reverse angle of get_lobbying_filings: filings show who pays lobbyists; LD-203 shows where the lobbyists' own money goes. Coverage: 2008→present (~40K filings/year; roughly half are 'no contributions' certifications, excluded by default — set include_empty=true to see them). Record shape: one record per filing — filer (lobbyist name or registrant firm), filing_year + period (mid_year | year_end), nested contribution_items[] (contribution_type, contributor_name, payee_name, honoree_name, amount, date), flattened honoree_names[] / payee_names[] / contribution_types[], and contributions_total_usd (simple sum of item amounts). Filters: honoree_name is the political join — substring against any item's honoree (e.g., 'schumer'). registrant_name matches the firm; lobbyist_name the individual filer; payee_name the receiving committee. contribution_type exact values: 'feca' (campaign money), 'honorary', 'meeting', 'presidential_library', 'inaugural_committee'. Cross-source: pair with get_fec_contributions (the FEC's view of the same FECA money, itemized ≥$200), get_lobbying_filings (the same registrant's client work), get_member_profile (resolve the honoree to party/state/committees). Pure-publisher posture: filings as posted to the Senate LDA system; contributions_total_usd is arithmetic, not a score.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNodt_posted lower bound (YYYY-MM-DD inclusive).
untilNodt_posted upper bound (YYYY-MM-DD inclusive).
filer_typeNoWho filed: the individual lobbyist or the registrant firm.
payee_nameNoCase-insensitive substring against any item's payee (the committee/entity paid).
sort_orderNoDefault: desc (most recently posted first).
filing_uuidNoDirect lookup by LDA filing UUID. Fastest path.
filing_yearNoFiling year (2008→present).
honoree_nameNoCase-insensitive substring against any item's honoree — the covered official who benefited (e.g., 'schumer').
include_emptyNoInclude 'no contributions' certifications (~half of all filings). Default false.
lobbyist_nameNoCase-insensitive substring against the individual lobbyist's name.
registrant_nameNoCase-insensitive substring against the lobbying firm / organization name.
contribution_typeNoExact type: 'feca', 'honorary', 'meeting', 'presidential_library', 'inaugural_committee'.

TDQS

A4.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, so the safety profile is covered. The description adds substantial extra context beyond annotations — coverage window (2008→present), volume (~40K filings/year), the fact that ~half are 'no contributions' certifications excluded by default, the record shape, and a 'pure-publisher posture' caveat that contributions_total_usd is arithmetic not a score. That is meaningful added behavior, but much of it duplicates schema-level filter semantics rather than revealing operational traits like rate limits or auth, so it lands above baseline without being exceptional.

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 definition and the reverse-angle framing before dense detail. It is long and repeats some schema content (contribution_type values, the honoree example appears twice), but nearly every clause carries distinct information. Efficient enough given a 13-parameter tool with no output schema, with minor 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?

No output schema exists, so the description must carry return semantics — and it does: one record per filing, filer fields, filing_year/period, nested contribution_items[], flattened arrays, and contributions_total_usd. Combined with coverage window and the empty-certification caveat, an agent has everything needed to call and interpret results.

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 the baseline is 3. The description adds genuine conceptual meaning beyond the schema: honoree_name is framed as 'the political join' with an example, contribution_type values are glossed with semantic intent ('feca' = campaign money), and include_empty is explained in terms of the ~half of filings that are certifications. This lifts it above baseline, though the contribution_type enum list is largely a restatement of 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+resource (LD-203 semiannual contribution reports) and immediately scopes what it contains: contributions by lobbyists/firms themselves, with the honoree concept called out. It explicitly distinguishes itself from the closest sibling ('the reverse angle of get_lobbying_filings: filings show who pays lobbyists; LD-203 shows where the lobbyists' own money goes').

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?

Provides explicit routing: use get_lobbying_filings for client work, get_fec_contributions for the FEC view of the same FECA money, get_member_profile to resolve the honoree. It also states a default behavior (empty certifications excluded) and how to override it, which is directly actionable usage guidance.

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

get_material_eventsA
Read-only
Inspect

Returns Form 8-K filings — the SEC's 'current report' form, filed within 4 business days of any material event at a publicly-traded company. Each record is one filing, with item_codes declaring WHAT kind of event(s) it covers. Use this when the user asks about: recent CEO/CFO departures or appointments, M&A announcements, earnings releases, big contract wins, restructurings, going-concern warnings, exec compensation changes, or any 'what just happened at this company' question. Item codes (most-used; many more exist): 1.01 Entry into a Material Definitive Agreement 1.02 Termination of a Material Definitive Agreement 2.01 Completion of Acquisition or Disposition of Assets 2.02 Results of Operations (earnings releases live here) 2.03 Creation of a Material Direct Financial Obligation 3.01 Notice of Delisting / Failure to Satisfy Listing Rule 3.02 Unregistered Sales of Equity Securities 4.01 Changes in Registrant's Certifying Accountant 5.02 Departure / Election / Appointment of Officers + Directors 5.07 Submission of Matters to a Vote of Security Holders 7.01 Regulation FD Disclosure 8.01 Other Events (catch-all) 9.01 Financial Statements and Exhibits — NOTE: nearly every 8-K ticks this 'paperwork box.' Searching JUST for 9.01 returns the firehose; combine it with another item_code to focus. item_codes filter is OR-semantic: pass an array, match any filing containing AT LEAST ONE of those codes. Capped at 30 codes per query (Firestore array-contains-any limit). Examples: ['5.02'] for exec changes; ['1.01','2.01'] for any deal activity (LOI or close); ['2.02'] for earnings. Amendments (8-K/A) get their own row with is_amendment: true. The original 8-K stays in place. v1 does NOT populate original_accession_number; agents can find candidates by matching (ticker, period_of_report) across rows. Filter is_amendment: false for clean original-only views. v1 does not extract the prose body — primary_document_url points agents at the source HTML for direct fetch. The structured items are what's queryable here.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive.
sort_byNoField used for ordering and for since/until filters. filing_date = when filed with SEC; period_of_report = when the underlying event occurred. Default: filing_date. NOTE: a small number of 8-Ks (Reg-FD-only filings, item-7.01 disclosures) lack period_of_report at the SEC source — those rows fall back to filing_date ordering automatically, so sort_by='period_of_report' won't bury them.
item_codesNoArray of item codes to filter on (OR semantics). E.g., ['5.02'] for exec changes, ['1.01','2.01'] for any deal activity. Max 30 codes per query.
sort_orderNoDefault: desc (most recent first).
company_cikNoSEC CIK number (10-digit, padded with leading zeros). Alternative to ticker.
is_amendmentNoFilter to only original 8-Ks (false) or only amendments / 8-K/A filings (true). Omit to include both.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnly, openWorld, non-destructive), and the description layers on non-obvious behavior: OR-semantics and the 30-code Firestore cap, how 8-K/A amendments are stored as separate rows with is_amendment, that v1 leaves original_accession_number unpopulated, and that v1 does not extract the prose body so primary_document_url must be fetched. This is rich context beyond the structured fields.

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 definition before the usage triggers, and every block (item codes, amendment handling, v1 limitations) carries information. The item-code glossary is long but justified; there is minor redundancy with the schema's item_codes example text.

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 no output schema, the description compensates by describing the record shape, the item_codes field, the amendment row model, and the primary_document_url escape hatch for prose. An agent has everything needed to query and to explain results to a user.

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 real value: a glossary mapping item codes to event meanings that is absent from the schema, plus the explicit 30-code cap and OR semantics that shape how item_codes should be constructed. It stops short of full syntax depth for the date/sort parameters, which the schema already handles.

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 (SEC Form 8-K current reports), defines it inline ('filed within 4 business days of any material event'), and explains the record granularity ('Each record is one filing, with item_codes declaring WHAT kind of event(s)'). An agent can distinguish this from sibling filing tools like get_insider_filings or get_proxy_filings purely from the text.

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 enumerates the trigger questions ('recent CEO/CFO departures or appointments, M&A announcements, earnings releases...') and gives concrete item_code recipes for each use case (['5.02'], ['1.01','2.01'], ['2.02']). It also warns against a specific misuse — searching only 9.01 returns the firehose.

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

get_member_profileA
Read-only
Inspect

Returns Congressional member profiles from the unitedstates/ congress-legislators catalog. Each record is one current House Representative or Senator, keyed by bioguide_id (the permanent member identifier — e.g., 'C001035' for Susan Collins). Use this when the user asks about: which committees a member sits on, who chairs the Senate Banking Committee, all Republicans on House Armed Services, party/state/district lookup for a specific member, or to enrich congressional_trades records with member context (party + state + committee assignments). Filter by bioguide_id for a direct fetch; by member_name for a case-insensitive substring search; by committee_id (e.g., 'HSAS' for House Armed Services, 'SSAF' for Senate Agriculture, 'HSAG15' for the Forestry & Horticulture subcommittee under House Ag) to find all members of a committee. Combine state + chamber + party for caucus-level queries. Committee codes follow the Library of Congress 'Thomas' convention: House full committees: HSAG (Agriculture), HSAS (Armed Services), HSAP (Appropriations), HSBA (Financial Services), HSED (Education), HSEN (Energy & Commerce), HSII (Natural Resources), HSJU (Judiciary), HSWM (Ways and Means), etc. Senate full committees: SSAF (Ag), SSAS (Armed Services), SSAP (Appropriations), SSBK (Banking), SSCM (Commerce), SSEG (Energy), SSFI (Finance), SSHR (HELP), SSJU (Judiciary), etc. Subcommittees append the subcommittee thomas_id: HSAG15, HSBA00. Photo URLs are constructed (theunitedstates.io/images/congress/ original/{bioguide_id}.jpg) but Cloudflare-protected — clients fetch directly. Senate class field (1/2/3) on senators only.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 600 (~current Congress size).
partyNo'Democrat' | 'Republican' | 'Independent' | etc. Exact match — uses the YAML's spelling.
stateNo2-letter state abbreviation (e.g., 'ME', 'CA'). Filters to members from that state — useful with chamber=senate to get the 2 senators from a state.
chamberNoFilter to House Representatives or Senators.
bioguide_idNoPermanent member identifier — letter + 6 digits (e.g., 'C001035' for Susan Collins, 'P000197' for Nancy Pelosi). Direct doc lookup, fastest path.
member_nameNoCase-insensitive substring against full_name. Example: 'Pelosi' returns Nancy Pelosi.
committee_idNoThomas committee code (full committee like 'HSAS' or subcommittee like 'HSAG15'). Returns all members of that committee.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so safety is covered. The description adds substantial behavioral context beyond annotations: the data source, that records are limited to current members, permanent bioguide_id keying, Library of Congress Thomas committee-code conventions, Cloudflare-protected photo URLs, and the Senate class field.

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 primary key, then moves through use cases, filter guidance, committee-code details, and output caveats. It is long but appropriately structured for a complex catalog tool. Some detail, such as the long committee-code list and photo URL note, could be trimmed, but each portion generally 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?

Given seven parameters, full schema coverage, rich annotations, and no output schema, the description is complete enough for selection and invocation. It explains the record scope, key identifier, usage scenarios, filter behavior, committee-code conventions, and notable output caveats such as photo URL handling and Senate class.

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 the schema already documents each parameter; baseline is 3. The description adds meaningful semantics beyond the schema, including committee-code taxonomy examples (e.g., HSAS, SSAF, HSAG15) and guidance to combine state + chamber + party for caucus-level queries. It stops short of adding context for every parameter, but the extra committee and combination guidance is valuable.

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: returns Congressional member profiles from the unitedstates/congress-legislators catalog. It specifies the scope as one current House Representative or Senator and identifies the primary key bioguide_id with an example. The scope distinguishes it from related tools like get_congressional_trades.

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 gives multiple explicit when-to-use examples: committee assignments, committee chairs, caucus queries, party/state/district lookup, and enriching congressional_trades records. It also provides filter-selection guidance, such as bioguide_id for direct fetch and member_name for substring search. It does not state when not to use the tool or name an alternative sibling tool explicitly.

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

get_money_market_fundsA
Read-only
Inspect

Returns Form N-MFP3 monthly money-market fund reports — one record per (fund series, month): fund category (Government / Prime / Single State…), net assets, shares outstanding, weighted average maturity (wam_days) and life (wal_days), the fund's DAILY daily/weekly liquid-asset percentages for the month (verbatim fractions of 1 — the money-market stress series), monthly gross subscriptions/redemptions ON N-MFP3 ONLY, and stable-NAV posture. ⚠ MONTHLY FLOWS ARE NOT ON EVERY RECORD. gross_subscriptions_month / gross_redemptions_month are filed per SHARE CLASS on N-MFP3 and are served as the sum across a filing's classes. N-MFP2 and N-MFP do not ask for monthly flows at all (N-MFP2 reports weekly), so those rows carry null — the source's silence, not ours. Read flows_basis to tell them apart: "monthly_sum_of_classes" or "not_filed_monthly". form_type says which form the record came from. ⚠ A SUM COVERS ONLY THE CLASSES THAT REPORTED. flows_classes_reporting_subscriptions / _redemptions say how many did; compare each against total_share_classes, which is how many EXIST. The two counts are separate because a class can report one figure and omit the other. WHERE THOSE FIELDS ARE ABSENT, COVERAGE IS NOT RECORDED — that is NOT a statement that the sum is complete. Rows written before 2026-09-11 predate the fields and are not backfilled for them. Use this when the user asks about: money-market fund assets or flows, fund liquidity levels, WAM positioning as a rates signal, prime-vs- government fund dynamics, or a specific fund family's money funds. The adviser_file_number (801-…) joins get_investment_advisers for the manager's full ADV profile; registrant cik joins other EDGAR datasets. Each fund files monthly — filter series_id + sort report_date asc to read one fund's history; filter by report_date (since/until) for a cross-fund month snapshot. Coverage: 2010-11→present across all THREE form generations, with per-era cadence differences kept verbatim: N-MFP3 records (2024-06→) carry DAILY liquidity/shadow-NAV/yield series with real dates; N-MFP2 records (2016-10→2024-06) carry WEEKLY Friday points labeled with the source's own fridayWeek1..5 keys in the date field (the filing reports week numbers, not dates — never fabricated); original N-MFP records (2010-11→2016-10) carry single month-end shadow-NAV + yield points and NO liquidity percentages (that reporting began with the 2014 reforms). series_name is empty before 2024 (not in the older XML). The per-security portfolio schedule and per-class yields live in the filing XML — follow source_url (v1.1 scope). Pure-publisher posture: the fund's reported numbers as filed, parsed by KeyVex — no derived stress scores; liquidity thresholds are for agents to apply.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoRegistrant CIK (any zero-padding).
limitNoMaximum records. Default 50, max 500.
sinceNoreport_date lower bound (YYYY-MM-DD inclusive).
untilNoreport_date upper bound (YYYY-MM-DD inclusive).
sort_byNoDefault report_date (newest month first).
fund_nameNoCase-insensitive substring against registrant or series name.
series_idNoEDGAR series ID (e.g. 'S000096464') — one fund's monthly history.
sort_orderNoDefault desc.
fund_categoryNoVerbatim N-MFP category: 'Government', 'Prime', 'Single State', 'Other Tax Exempt', …
is_retail_fundNoFilter to retail (true) / institutional (false) funds.
accession_numberNoDirect lookup by EDGAR accession number.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnly/openWorld/non-destructive; the description carries far more: null flow semantics (N-MFP2/N-MFP don't file monthly), flows_basis discriminator, per-class reporting coverage counts vs total_share_classes, the explicit caveat that absent coverage fields do NOT imply completeness, the pre-2026-09-11 no-backfill boundary, verbatim fraction-of-1 units, and the 'pure-publisher, no derived scores' posture.

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 purpose before the caveats, and nearly every sentence earns its place given the multi-generation data quirks. It is very dense and leans on repeated ⚠/caps warnings, which is scannable but bordering on noisy for a description of this length.

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 11-param, no-output-schema tool spanning three form generations, the description supplies the era-by-era cadence differences, null/coverage semantics, join keys, and filtering recipes an agent needs to call it correctly. No output schema exists, yet the returned fields and their caveats are explained where it matters.

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 11 params and baseline is 3. The description adds real usage semantics beyond the schema: series_id is framed as 'one fund's monthly history', report_date filters as cross-fund month snapshots, cik/adviser_file_number as join keys, and sort combinations as patterns — genuinely useful invocation context.

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: returns Form N-MFP3 monthly money-market fund reports, one record per (fund series, month), and enumerates the fields delivered (net assets, WAM/WAL, daily/weekly liquid-asset percentages, flows, stable-NAV posture). It also distinguishes itself from sibling datasets (N-MFP2/N-MFP generations, get_investment_advisers joins, get_nport_filings-adjacent XML) so an agent can place it 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?

Gives explicit when-to-use triggers ('money-market fund assets or flows, fund liquidity levels, WAM positioning as a rates signal, prime-vs-government fund dynamics, or a specific fund family's money funds') plus concrete filtering recipes (series_id + sort report_date asc for one fund's history; report_date for a cross-fund snapshot). It does not name a sibling to use instead for portfolio-level data beyond pointing at source_url, so it falls just short of full when-not guidance.

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

get_nlrb_casesA
Read-only
Inspect

Returns NLRB (National Labor Relations Board) case filings: unfair- labor-practice charges and union representation/election petitions. Use this when the user asks about: union organizing at a company, labor disputes or ULP charges, union election petitions and outcomes, decertification efforts, or a company's labor-relations record. Case numbers follow {region}-{type}-{sequence}, e.g. '03-CA-390171' (NLRB Region 03, CA charge). The middle code determines the case family: C-cases are ULP CHARGES against an employer (CA) or a union (CB, CC, CD, CE, CG, CP) — allegations of unlawful labor practices. R-cases are REPRESENTATION petitions — RC (union seeks certification), RD (employees seek decertification), RM (employer-filed), plus UD/UC/AC unit matters. Each record carries case_type ('ULP' or 'representation') and case_subtype (the raw code). The name field is the named party on the filing — usually the employer, but on CB/CC-type charges it is the union being charged. employer_name matches against it as a substring. Representation cases carry eligible_voters, certified_representative (filled after a won election), and unit_sought (the bargaining-unit description). FRESHNESS CAVEAT: cases mutate after filing — status flips Open→Closed and date_closed / reason_closed / certified_representative fill in later. The daily sync re-pulls a trailing 180-day date_filed window, so those fields on cases FILED MORE THAN ~180 DAYS AGO may lag the source until a periodic full re-pull; the source_url case page is always current. Filter combinations note: server-side indexes support ONE of state / case_type combined with the date_filed sort + since/until. Other filters (employer_name substring, case_subtype, status, region, state+case_type together) post-filter client-side over a widened fetch window. Pure-publisher posture: NLRB's public case rows as published — no outcome scoring. Each record's source_url links to the nlrb.gov public case page (which also carries docket activity and related documents not in this dataset).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum cases to return. Default 50, max 500.
sinceNodate_filed lower bound (YYYY-MM-DD inclusive).
stateNoTwo-letter state/territory code of the case site (e.g., 'NY', 'CA', 'PR').
untilNodate_filed upper bound (YYYY-MM-DD inclusive).
regionNoTwo-digit NLRB region number from the case-number prefix (e.g., '03' Buffalo, '13' Chicago). Client-side filter.
statusNoCase status. Client-side filter.
sort_byNoSort key. Only date_filed is supported (the default).
case_typeNoCase family: 'ULP' = unfair-labor-practice charges (C-cases), 'representation' = election/unit petitions (R-cases).
sort_orderNoDefault: desc (most recently filed first).
case_numberNoDirect lookup by NLRB case number (e.g., '03-CA-390171'). Fastest path.
case_subtypeNoExact case-number code (e.g., 'CA' charge against employer, 'CB' against union, 'RC' certification petition, 'RD' decertification). Client-side filter.
employer_nameNoCase-insensitive substring against the named party (e.g., 'starbucks', 'amazon'). Usually the employer; on CB-type charges the union. Client-side filter.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnly, non-destructive, openWorld), and the description goes well beyond that: it discloses the freshness caveat (trailing 180-day re-pull window; older cases may lag the source), the split between server-side indexed filters and client-side post-filtering over a widened window, and the fact that source_url is always current. This is exactly the kind of behavioral context annotations cannot carry.

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 triggering contexts are front-loaded, then grammar, then caveats — a sensible order for a dense tool. It is long and a few clauses (e.g., the 'Pure-publisher posture' editorial) are near-filler, but given 12 parameters and no output schema most sentences carry necessary 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 12-parameter, zero-required, no-output-schema tool, the description supplies what the structured fields omit: what each record family contains (eligible_voters, certified_representative, unit_sought), how filters interact, and how fresh the data is. An agent has everything needed to build a correct query and interpret the results.

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 already 100%, so the baseline is 3, but the description adds real meaning: the {region}-{type}-{sequence} case-number format, what the middle code signifies, and the important caveat that the `name` field (matched by employer_name substring) is usually the employer but the union on CB/CC charges. It also explains which filter combinations the server-side indexes actually support, which the schema only hints at with 'Client-side filter'.

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 (Returns) and resource (NLRB case filings) and immediately scopes it to two concrete families (ULP charges and representation/election petitions). It is unmistakable against siblings like get_osha_enforcement or get_enforcement_actions because it defines the domain, the case-number grammar, and the record families.

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 'Use this when the user asks about: union organizing... labor disputes or ULP charges... decertification efforts... a company's labor-relations record' clause gives clear triggering contexts. It stops short of naming alternatives (e.g., unified_search) or stating when NOT to use it, so it is strong context without explicit routing/exclusions.

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

get_nonprofit_filingsA
Read-only
Inspect

Returns IRS Form 990-series e-filing records — the registry of every e-filed nonprofit return the IRS has released, 2017→present (~5.5M filings; ~400-750K/yr). One record per return: EIN, organization name, return type (990 = full; 990EZ = small; 990PF = private foundation; 990T = unrelated business income; the 2019-era index also carries IRS codes 990EO/990O verbatim), the tax period covered (YYYYMM), and the IRS release year. Use this when the user asks: does nonprofit X file with the IRS, when did a foundation last file, which returns has an EIN filed, or to anchor a nonprofit's identity (EIN) before joining grants / lobbying / OIG data by name. Records carry the filing's extracted FINANCIALS: total_revenue, total_expenses, total_assets_eoy, net_assets_eoy, and officers[] — top 25 by reported compensation with name/title. Coverage (reconciled 2026-07-08): 100% for release years 2019-2026, 97% for 2018, 69% for 2017 — the shortfall is IRS-side (the pre-2017 XML archives that held those filings' documents were retired by the IRS; the registry rows remain, without financials). Meanings follow the form: for 990T, total_revenue is unrelated-business taxable income. Officer compensation is as reported to the IRS. sub_date is set only for 2019-era records (later IRS indexes carry only the year — KeyVex never fabricates dates); tax_period is the reliable time axis. A nonprofit's fiscal year varies — tax_period 202506 means the period ENDING June 2025. Pure-publisher posture: the IRS index rows as published.

ParametersJSON Schema
NameRequiredDescriptionDefault
einNoEmployer Identification Number (any format — digits extracted).
nameNoCase-insensitive substring against the organization name.
limitNoMaximum records. Default 50, max 500.
sinceNotax_period lower bound — 'YYYY-MM' or 'YYYYMM' (inclusive).
untilNotax_period upper bound — 'YYYY-MM' or 'YYYYMM' (inclusive).
object_idNoDirect lookup by IRS OBJECT_ID.
sort_orderNoSort by tax_period. Default desc.
return_typeNoIRS code verbatim: '990', '990EZ', '990PF', '990T' (also '990EO'/'990O' in 2019-era records).
submission_yearNoIRS release/index year (2017→present; financials partial for 2017 — IRS retired the pre-2017 XML archives).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already cover the read-only/safe profile, yet the description adds substantial context: coverage percentages reconciled by date, why 2017 financials are partial (IRS retired pre-2017 XML), sub_date being set only for 2019-era records, and a 'never fabricates dates' guarantee. This is exactly the behavioral detail 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?

Front-loaded with what it returns before the usage and caveat material. It is long (~350 words) with several parenthetical asides, but nearly every sentence carries distinct information needed by a data-catalog consumer with no output 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?

With no output schema and 9 parameters, the description fully compensates: it enumerates returned fields (EIN, name, return_type, tax_period, release year, financials, officers), explains semantics per form type, and documents coverage limits. An agent has everything needed to call and interpret results.

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. The description goes beyond it by decoding return_type values (990 full, 990EZ small, 990PF foundation, 990T UBI), explaining tax_period as YYYYMM with a fiscal-year ENDING example, and clarifying that since/until bound tax_period.

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 ('Returns IRS Form 990-series e-filing records') and immediately scopes it (2017→present, one record per return). It also positions the tool against siblings by describing its role as an EIN identity anchor 'before joining grants / lobbying / OIG data by name,' so an agent can tell it apart from those tools.

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, concrete when-to-use scenarios ('does nonprofit X file with the IRS, when did a foundation last file, which returns has an EIN filed'). It does not name an alternative tool or state when-not-to-use, but the use-case framing is strong and unambiguous.

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

get_nport_filingsA
Read-only
Inspect

Returns SEC Form N-PORT filings — monthly portfolio reports from registered investment companies (mutual funds, ETFs, closed-end funds). Use this when the user asks about: recent fund portfolio filings, when a specific fund family last reported, monthly cadence of fund disclosures, or to bridge from a fund trust name to the primary_doc.xml that contains full per-holding portfolio detail. Source: SEC EDGAR full-text search. Covers both NPORT-P (original filing) and NPORT-P/A (amendments). N-PORT is filed within 60 days of each month-end; period_ending tells you which month the report covers. v1A returns metadata only: filer trust name + CIK, period_ending, filing type, SEC investment company file number (e.g., '811-21864'), filer state + state of incorporation, and the URL to the full primary_doc.xml. Per-holding portfolio detail (every security in the fund's portfolio with quantity, fair value, currency, etc.) lives in that XML — agents follow the URL when they need security-level data. Pairs with get_institutional_holdings (13F): 13F is quarterly, filed by INVESTMENT MANAGERS (Berkshire, Vanguard, BlackRock); N-PORT is monthly, filed by the FUND TRUST. Together = fresher snapshots across two complementary universes (manager-level vs fund-level).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNofile_date lower bound (YYYY-MM-DD inclusive).
untilNofile_date upper bound (YYYY-MM-DD inclusive).
sort_byNoDefault: file_date (most recently filed first). period_ending sorts by the month the report covers.
filer_cikNoFund trust's SEC CIK (1-10 digits; we zero-pad internally).
filing_idNoEDGAR accession number. Direct doc lookup, fastest.
filer_nameNoCase-insensitive substring against the fund trust name (e.g., 'wisdomtree', 'vanguard', 'fidelity').
sort_orderNoDefault: desc.
is_amendmentNoWhen set, restricts to NPORT-P/A amendments (true) or original NPORT-P (false). Default: both.
period_endingNoFilter to a specific reporting period — the month-end the filing covers (YYYY-MM-DD).
sec_file_numberNoSEC Investment Company file number, e.g., '811-21864'. Each fund trust has a stable number.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover the safety profile (readOnly, openWorld, non-destructive); the description adds substantive behavior: source is SEC EDGAR full-text search, covers NPORT-P and NPORT-P/A, filing cadence is within 60 days of month-end, and v1A returns metadata only with per-holding detail living in the linked XML. This goes well beyond what the annotations disclose.

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?

It is long but dense and front-loaded, leading with the resource definition before use cases and return shape. Every paragraph earns its place, though the volume is on the heavier side for a single tool description.

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 no output schema, the description carries the return-value burden and does so fully: it lists the metadata fields returned (filer trust name + CIK, period_ending, filing type, file number, state, and primary_doc.xml URL) and directs agents to the XML for security-level data. Nothing needed 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?

Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: it explains that period_ending identifies which month the report covers (vs file_date), and clarifies the NPORT-P vs NPORT-P/A amendment distinction behind is_amendment. It does not add much for the remaining params, but it does exceed the schema-only floor.

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+resource (returns SEC Form N-PORT monthly portfolio reports from registered investment companies) and defines the domain (mutual funds, ETFs, closed-end funds). It explicitly differentiates itself from the closest sibling, get_institutional_holdings (13F), by contrasting manager-level vs fund-level and quarterly vs monthly.

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 enumerates concrete when-to-use scenarios ('recent fund portfolio filings', 'when a specific fund family last reported', 'bridge from a fund trust name to primary_doc.xml') and names the complementary tool. The routing decision is explicit rather than inferred.

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

get_ofac_sdnA
Read-only
Inspect

Returns OFAC Specially Designated Nationals (SDN) sanctions list entries, republished as-is (not a screening service; verify against treasury.gov). Use this for: sanctions-program queries (e.g., 'who's on the Russia SDN list'), or cross-referencing named individuals / entities against the canonical US sanctions list. Source: US Treasury OFAC — sanctionslistservice.ofac.treas.gov. ~19,000 entries refreshed daily. Each entry represents a person, entity, vessel, or aircraft sanctioned by the US government under one or more programs (CUBA, IRAN, SDGT [terrorism], NPWMD [WMD proliferation], RUSSIA-EO14024, etc.). US persons (citizens, residents, US-domiciled companies) are legally prohibited from transacting with SDNs — this is the canonical list published by OFAC. Filter by name substring for primary lookups. entity_type values: 'individual', 'entity', 'vessel', 'aircraft'. Every SDN record carries exactly one of the four — companies are 'entity'. program is a substring filter against the comma-delimited Program field (e.g., 'iran', 'russia', 'narcotics'). remarks substring catches aliases, DOB / passport references, and related-party hints. Direct ent_num lookup is fastest (OFAC's stable entity number). WHAT'S NOT IN v1A (data-model limitations to know about): the schema does NOT include designation_date (when OFAC originally added the entry). OFAC's basic SDN.csv source file only provides 12 columns and omits this — the date lives in OFAC's advanced XML and a separate 'Recent Actions' page on their site. So 'sanctions added in the last N days' is not directly queryable via this tool — point users at ofac.treasury.gov/recent-actions for that specific question. v1.1 polish will add advanced-XML ingestion to capture designation_date. Also: there's no since/until filter and no date sort option for the same reason — the only sort options are name and ent_num. Pure-publisher posture: KeyVex returns OFAC's published list as-is. No derived 'risk score' or 'similarity match' — agents handle fuzzy matching downstream. For broader list coverage, agents should also consult the US Consolidated Screening List (get_screening_list) which spans 12 export-control / sanctions lists from State + Commerce + Treasury.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoCase-insensitive substring against the primary listed name (e.g., 'kim jong un', 'gazprom').
limitNoMaximum entries to return. Default 50, max 500.
ent_numNoDirect OFAC entity number lookup. Fastest path.
programNoSubstring against the comma-delimited program field (e.g., 'IRAN', 'RUSSIA', 'SDGT' for terrorism, 'NARCOTICS').
remarksNoSubstring against free-text remarks (aliases, DOB / passport references, related-party hints).
sort_byNoDefault: ent_num.
sort_orderNoDefault: asc.
entity_typeNoFilter to one entity type. 'entity' covers companies / orgs; 'individual' for people; 'vessel' / 'aircraft' for transports.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations cover readOnly/openWorld/destructive, but the description adds substantial context beyond them: republished as-is with no risk score, ~19,000 entries refreshed daily, a legal prohibition notice, and explicit v1A data-model limitations (no designation_date, no since/until filter, sort limited to name/ent_num). Return-format/pagination behavior is not described, keeping it below 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?

Front-loaded with purpose and usage before the long v1A limitations block, and every section carries information. However it is verbose with some repetition ('canonical US sanctions list' / 'canonical list published by OFAC'), so not maximally 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?

For an 8-param tool with no output schema, the description covers what an entry represents, the domain scope, filtering semantics, and honest data-model gaps. Nothing critical to calling it correctly appears to be 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%, so the baseline is 3, but the description adds meaning beyond the schema: entity_type semantics ('companies are entity'), the substring nature of program and remarks filters, and the emphasis on ent_num as the fastest path. Some of this overlaps the schema, but it adds contextual framing.

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 ('Returns OFAC Specially Designated Nationals (SDN) sanctions list entries') and explicitly disclaims what it is not ('not a screening service'). It names the sibling get_screening_list and the recent-actions alternative, so the agent can distinguish it from nearby 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?

Provides explicit 'Use this for:' cases (sanctions-program queries, cross-referencing named individuals/entities), states when-not (designation_date / 'added in last N days' questions point at recent-actions), and routes broader coverage to get_screening_list. When, when-not, and alternatives are all present.

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

get_oig_exclusionsA
Read-only
Inspect

Returns entries on the HHS Office of Inspector General 'List of Excluded Individuals/Entities' (LEIE). Anyone on this list is barred from billing Medicare, Medicaid, or any federal healthcare program. Updated monthly by OIG; KeyVex re-scrapes monthly and overwrites. Use this when the user asks about: healthcare-fraud exclusions, Medicare/Medicaid program-integrity research (not employment or eligibility decisions about individuals — Terms §8A), geographic concentration of exclusions, or a specific person/business listed on LEIE. Cross-source tip: pair with get_federal_contracts to flag contractors who appear on the exclusion list. A government contractor with an OIG exclusion is worth checking against the official LEIE at oig.hhs.gov. Statutory exclusion types (the most common): - 1128a1 Conviction of program-related crimes - 1128a2 Conviction relating to patient abuse - 1128a3 Felony conviction relating to healthcare fraud - 1128a4 Felony conviction relating to controlled substances - 1128b4 License revocation, suspension, surrender - 1128b5 Exclusion or suspension under federal/state healthcare - 1128b7 Fraud, kickbacks, and other prohibited activities - 1128b8 Entities controlled by a sanctioned individual Scope: the LEIE lists only CURRENTLY-ACTIVE exclusions — OIG removes a party once reinstated (reinstatements are a separate OIG publication not ingested here). So every record is, by definition, an active exclusion, and reinstatement_date is effectively always empty. Pure-publisher posture: we surface the listing as-published. Some names match common-name individuals who aren't the excluded party — the agent / user is responsible for context disambiguation (DOB, address, NPI).

ParametersJSON Schema
NameRequiredDescriptionDefault
npiNoExact 10-digit National Provider Identifier.
cityNoCase-insensitive substring against city.
nameNoCase-insensitive substring against full_name (covers both individuals and businesses).
limitNoDefault 50, max 500.
sinceNoISO date (YYYY-MM-DD). Applied to sort_by field.
stateNoTwo-letter state code (e.g. 'NY', 'CA'). Case-insensitive.
untilNoISO date (YYYY-MM-DD).
sort_byNoDefault exclusion_date.
specialtyNoCase-insensitive substring against specialty.
sort_orderNoDefault desc.
is_businessNoFilter to businesses only (true) or individuals only (false).
business_nameNoCase-insensitive substring against business_name only.
exclusion_typeNoStatutory code (e.g. '1128a1', '1128b5').
general_categoryNoExact match (case-sensitive): 'PHARMACY', 'PHYSICIAN', 'OTHER BUSINESS', 'DME COMPANY', 'CLINIC', etc.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations cover safety (readOnlyHint, destructiveHint=false) and open-world scope, but the description adds substantial non-structured context: monthly OIG refresh with overwrite semantics, the fact that the LEIE contains only currently-active exclusions so reinstatement_date is effectively always empty, and an explicit name-collision caveat (common-name matches; agent/user must disambiguate via DOB/address/NPI). That is exactly the kind of trait annotations cannot express.

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 definition and the when-to-use guidance, which is correct ordering. The statutory-code block is genuinely load-bearing for interpreting exclusion_type, but a few sentences are promotional or restate scope ('Pure-publisher posture', the oig.hhs.gov reminder, the repeated statement about active-only listings) and could be trimmed.

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 14-parameter tool with no output schema, the description covers source, freshness, legal meaning, scope limits, filter semantics, and the disambiguation caveat well. It stops short of describing the shape of a returned record (fields beyond the reinstatement_date note), which the absence of an output schema would otherwise require.

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 real semantic value the schema lacks: it enumerates the statutory exclusion codes (1128a1 through 1128b8) and their meanings, which is what exclusion_type filters on, and it clarifies that since/until are applied to the sort field and that results are limited to active exclusions. It still doesn't explain how the geographic/specialty filters interact or what a returned record contains.

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 ('Returns entries on the HHS OIG List of Excluded Individuals/Entities (LEIE)') and immediately defines what the list means (barred from billing Medicare/Medicaid/federal healthcare programs). This clearly separates it from adjacent screening siblings like get_ofac_sdn and get_screening_list by naming the exact source and its legal consequence.

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-to-use list (healthcare-fraud exclusions, program-integrity research, geographic concentration, a specific person/business on LEIE), an explicit when-not ('not employment or eligibility decisions about individuals — Terms §8A'), and a cross-source pairing tip with get_federal_contracts. Nothing about routing 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.

get_open_paymentsA
Read-only
Inspect

Returns CMS Open Payments records — the Sunshine Act database of every payment / transfer of value from drug + device manufacturers and GPOs to US physicians, non-physician practitioners, and teaching hospitals (~15M records per program year, 2019→present). LIVE passthrough to CMS's own API: results reflect CMS's current data and total_count is CMS's authoritative count for the filtered query (the results array is just the requested page). Use this when the user asks about: pharma/device money to doctors, a company's physician-payment footprint, speaker-fee / consulting / royalty programs, industry funding of research (with ClinicalTrials.gov IDs), or physician ownership stakes in manufacturers. payment_type selects the dataset (schemas differ; rows are CMS's fields verbatim): general (default) — meals, travel, consulting, speaker fees, royalties, honoraria. Fields incl. nature_of_payment_or_transfer _of_value, name_of_drug_or_biological_or_device_or_medical supply_1, covered_recipient_specialty_1. research — research payments incl. name_of_study, clinicaltrials_gov_identifier, preclinical_research_indicator. ownership — physician ownership/investment interests (total_amount_invested_usdollars, value_of_interest, terms_of_interest); recipient fields are physician*. summarize=true returns CMS's own pre-aggregated per-(company, nature) totals for the year — transaction counts + dollar totals per payment nature. The nature codes in that dataset ship without a public CMS legend; KeyVex labels the seven codes it has VERIFIED by exact count+total reconciliation against detail data (1=Consulting Fee, 2=Speaker/faculty compensation, 6=Food and Beverage, 7=Travel and Lodging, 9=Charitable Contribution, 10=Royalty or License, 14=Grant); unverified codes pass through with an empty label rather than a guess. Matching: company is a substring (matches subsidiaries: 'pfizer' catches PFIZER INC.); recipient names are EXACT (CMS stores uppercase; we uppercase for you); npi is the exact National Provider Identifier — the precise join key to get_oig_exclusions. Payments are attributed to the manufacturer AS FILED — no ticker/CIK; try the operating-company name. Program years: 2019 through the latest published year (CMS refreshes semiannually; year defaults to the latest). Pagination: limit ≤ 500 per page (CMS cap), use offset for more. Pure-publisher posture: CMS's records as filed, parsed by KeyVex (the source record is authoritative) — no derived influence scores. Disclosure ≠ wrongdoing; these are lawful, statutorily-disclosed payments.

ParametersJSON Schema
NameRequiredDescriptionDefault
npiNoRecipient National Provider Identifier (exact, 10 digits). Precise join key to get_oig_exclusions.
yearNoProgram year (e.g., 2023). Default: latest published year.
limitNoRecords per page. Default 25, max 500 (CMS page cap).
stateNoTwo-letter recipient state code (e.g., 'TX').
natureNoSubstring against nature of payment (general only; e.g., 'consulting', 'speaker', 'royalty', 'food').
offsetNoPagination offset into the filtered result set.
companyNoSubstring against the paying manufacturer / GPO name (e.g., 'pfizer', 'medtronic').
productNoSubstring against the associated drug / device name (general only; e.g., 'eliquis', 'ozempic').
summarizeNotrue = CMS's pre-aggregated per-(company, nature) yearly totals instead of individual payments.
payment_typeNoDataset: general (default — meals/consulting/speaker fees), research, or ownership (physician stakes).
recipient_last_nameNoRecipient physician / practitioner last name (exact, case-insensitive).
recipient_first_nameNoRecipient first name (exact, case-insensitive).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/non-destructive, and the description adds substantial context beyond them: it is a live passthrough to CMS, total_count is authoritative while the array is only one page, limit is capped at 500 by CMS, summarize returns pre-aggregated CMS totals, and unverified nature codes pass through with an empty label rather than a guess. This is exactly the extra behavioral context the bar asks for.

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?

Front-loaded well (what it is, then when to use it), but the block is very long and contains hard-wrapped fragments in the payment_type bullet list that read like formatting artifacts. Most content earns its place, yet it could be tightened considerably without losing meaning.

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, zero-required, no-output-schema read tool, the description covers dataset selection, matching rules, pagination, aggregation mode, temporal coverage and a disclosure-not-wrongdoing caveat. 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.

Parameters5/5

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

Schema coverage is 100% (baseline 3), but the description goes well beyond it: company is a substring that catches subsidiaries ('pfizer' → PFIZER INC.) while recipient names and npi are exact, nature and product apply only to the general dataset, and rows are CMS's fields verbatim with schema differences per payment_type. This adds real matching semantics the schema does not encode.

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 ('Returns CMS Open Payments records') and immediately scopes it (Sunshine Act, ~15M records/program year, 2019→present). The three payment_type datasets are enumerated with distinguishing fields, so an agent can tell what data it will get versus siblings like get_oig_exclusions or get_drug_adverse_events.

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?

Explicit 'Use this when the user asks about:' list covers pharma money to doctors, company payment footprint, speaker/consulting/royalty programs, research funding and ownership stakes. It also names the join key (get_oig_exclusions) and tells the agent to try operating-company names rather than tickers. Clear when-to-use and how to orient queries.

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

get_osha_enforcementA
Read-only
Inspect

Returns OSHA workplace-safety enforcement records from the Department of Labor's enforcement data: inspection cases (who was inspected, where, why, when) with optional violation citations attached (standard cited, violation type, penalties, abatement dates). Use this when the user asks about: a company's workplace-safety record, OSHA penalties or citations, fatality/catastrophe investigations, inspection activity by state or industry (NAICS), or contractor safety research. Result rows are INSPECTIONS. Pass include_violations=true to attach each inspection's citations under a violations array (or pass activity_nr for a direct lookup, which always includes them). min_penalty keeps only inspections with at least one violation whose initial or current penalty meets the threshold (implies include_violations). insp_type codes (DOL's own legend): A=Accident, B=Complaint, C=Referral, D=Monitoring, E=Variance, F=FollowUp, G=Unprog Rel, H=Planned, I=Prog Related, J=Unprog Other, K=Prog Other, L=Other-L, M=Fat/Cat (fatality/catastrophe), N=Unprog Emph. Each record carries insp_type_label with the decoded value. Violation viol_type codes: S=Serious, W=Willful, R=Repeat, O=Other, U=Unclassified. Violations carry delete_flag='X' when the source later deleted the citation — rows are kept with the flag, never dropped. Filter combinations note: server-side indexes support ONE of state / naics_code combined with the open_date sort + since/until. Other filters (establishment_name substring, insp_type, state+naics together, min_penalty) post-filter client-side over a widened fetch window. sort_by=case_mod_date is the 'recently updated cases' firehose and cannot be combined with state / naics_code / since / until. Pure-publisher posture: DOL's enforcement rows as published — codes kept verbatim (with the source's own legend decoded alongside), no safety scoring. Each record's source_url links to the osha.gov establishment inspection-detail page.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum inspections to return. Default 50, max 500.
sinceNoInspection open_date lower bound (YYYY-MM-DD inclusive).
stateNoTwo-letter site state (e.g., 'TX', 'CA').
untilNoInspection open_date upper bound (YYYY-MM-DD inclusive).
sort_byNoSort key. Default: open_date. case_mod_date = most recently UPDATED cases (cannot combine with state/naics_code/since/until).
insp_typeNoOne-letter inspection-type code (e.g., 'M' Fat/Cat, 'B' Complaint, 'H' Planned — full legend in the tool description).
naics_codeNoExact NAICS industry code of the inspected site (e.g., '238160' roofing contractors). Note: '000000' on many pre-NAICS-era records.
sort_orderNoDefault: desc (most recent first).
activity_nrNoDirect lookup by OSHA inspection activity number (e.g., '317465899'). Returns the inspection with its violations attached. Fastest path.
min_penaltyNoKeep only inspections with at least one violation whose initial or current penalty is >= this amount (dollars). Implies include_violations=true.
establishment_nameNoCase-insensitive substring against the inspected establishment's name (e.g., 'amazon', 'dollar general'). Client-side filter.
include_violationsNoWhen true, attaches each returned inspection's violation citations under a `violations` array (standard, type, penalties, abatement/contest dates). Default false.

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnly/openWorld/destructive=false) by disclosing index/filter-combination behavior, the case_mod_date 'firehose' that cannot combine with state/naics/since/until, client-side vs server-side filtering, delete_flag='X' retention semantics, and the pure-publisher (no safety scoring) posture. These are real behavioral traits an agent needs before calling.

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 use-cases are front-loaded, then return shape, then parameter/filter behavior, then data posture. Dense and mostly earning its space, though the insp_type and filter-combination passages are long enough that some tightening is possible.

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 12 parameters, no output schema, and no required fields, the description carries the burden well: it states rows are inspections, how violations attach, the meaning of min_penalty/activity_nr behavior, and source_url provenance. Nothing essential to correct invocation 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 description coverage is already 100%, so baseline is 3, but the description adds meaning the schema does not: full decoded insp_type legend (M=Fat/Cat etc.), violation viol_type codes, and the delete_flag='X' semantics. Schema enums for sort_by/insp_type are explained rather than merely restated.

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: returns OSHA workplace-safety enforcement records (inspections with optional violation citations), and explicitly says 'Result rows are INSPECTIONS'. This distinguishes it from sibling enforcement tools like get_epa_enforcement and get_nlrb_cases, which cover different agencies.

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 a concrete use-case list: company workplace-safety record, OSHA penalties/citations, fatality/catastrophe investigations, inspection activity by state or NAICS, contractor safety research. It also explains which paths to take (activity_nr for direct lookup, min_penalty implication, sort_by=case_mod_date constraint), but never names a sibling alternative or an explicit 'don't use this for X' exclusion.

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

get_planned_insider_salesA
Read-only
Inspect

A ticker search also returns rows this issuer FILED UNDER SYMBOLS IT NO LONGER LISTS (renames, filer typos, ADR spellings). Each row keeps ticker as SEC received it and gains current_ticker when the issuer trades under a different symbol today. Separately-listed share classes are NOT merged, and asking for a RETIRED symbol returns only rows filed under it — retired symbols get reissued to other companies. Returns Form 144 filings — notices of proposed sale by corporate insiders (officers, directors, 10%+ holders) under Rule 144 of the Securities Act. Each record is one planned-sale line from one filing. ⚠ aggregate_market_value is NULLABLE. A Form 144 that did not state a value now reports null rather than 0 — but a filer who genuinely stated 0.00 still reports 0, and that happens. Null never satisfies min_value and sorts last. ⚠ AND SOME FILERS STATE THE ISSUER'S MARKET CAP IN THAT BOX, WHICH PUTS THEM AT THE TOP OF A DESCENDING VALUE SORT. Measured 2026-09-04: 5 of the top 100 — SYF 4,000 shares stating $25.24bn ($6.31m per share), IT 860 shares stating $11.72bn. Dividing those by shares_outstanding on the same row gives $77.57 and $185.66, which are the real share prices. ⚠ THE CHECK CATCHES TWO OF THOSE FIVE, NOT ALL FIVE, AND SAYS SO RATHER THAN OVERSTATING ITSELF. TCMD, EPSM and XHR imply $36,017, $17,577 and $16,686 per share — absurd for those issuers, but below BRK.A's real $740,000 peak, so no per-row test separates them from a genuine high-priced sale. They still read 'checked'. Settling them needs a comparison against the day's actual price bar. Every row therefore carries aggregate_market_value_check: 'checked' the value implies a plausible price for the shares sold 'not_stated' no value was filed (distinct from a filed 0.00) 'no_share_count' no share count, so the check could not run 'implausible_looks_like_market_cap' implies a per-share price above any that has traded, and shares_outstanding yields a plausible one instead 'implausible_unexplained' implies an impossible price and shares_outstanding does not explain it — we can say it is not the sale value without being able to say what it is ⚠ The number is NOT corrected. SEC's bytes are served exactly as filed, and we do not invent a value the filer never stated. If you rank by this field, exclude anything whose check does not read 'checked' — otherwise the top of your list is market capitalisations. Use this when the user asks about: insiders who have announced they're about to sell, upcoming insider sales at a specific company, large planned sales by value, or which executives are signaling intent to exit positions. Form 144 is a forward-looking signal. It's filed BEFORE the actual sale, which later lands as a Form 4. The complement to get_insider_transactions: that tool tells you what insiders just did, this one tells you what they're about to do. Filing thresholds: ≥5,000 shares OR ≥$50,000 aggregate value. The aggregate_market_value is the insider's estimate at filing time; the actual sale price/value can differ. The approximate_sale_date is also an estimate — the real Form 4 transaction_date may be days later. Most Form 144 filings list one security line, but a single filing can cover multiple share classes (e.g., separate Class A + Class B). Each line is returned as its own record.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date, using sort_by as the date field.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive.
sort_byNoField used for ordering and for the since/until date filters. Default: filing_date.
min_valueNoFilter to filings with aggregate_market_value >= this amount (USD). Use to focus on large planned sales.
filer_nameNoFull or partial filer name; case-insensitive substring match. Example: 'Cook' matches Tim Cook's filings. NOTE: plain substring (not word-boundary) match — a short surname can match mid-word too (e.g. 'Huang' also matches 'CHUANG'). Pass a longer/fuller name to disambiguate a specific person.
sort_orderNoDefault: desc (most recent / largest first).
company_cikNoSEC CIK number (10-digit, padded with leading zeros). Alternative to ticker when known.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations cover only the safety profile (readOnly/destructive/openWorld), so the description carries the real behavioral burden and does it well: it discloses that aggregate_market_value is nullable and that null differs from a filed 0.00, that nulls never satisfy min_value and sort last, that filers sometimes place issuer market cap in that box (with measured evidence), that the value is never corrected, and the exact semantics of every aggregate_market_value_check value including its known blind spot. It also discloses ticker-rename/retired-symbol filtering behavior and the multi-share-class row expansion. This is a rare case of a description disclosing failure modes rather than only the happy path.

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?

Every paragraph carries real information, but the document is roughly 600 words with heavy ⚠/CAPS formatting and repetition — the market-cap-in-the-value-box problem is explained, then re-explained with per-ticker detail, then restated in the check-value definitions. More importantly it is not front-loaded: the actual purpose (Form 144 filings) appears only after a long ticker-caveat opening, so an agent skimming the first lines gets a symbol-rename warning instead of what the tool returns.

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?

There is no output schema, so the description must explain the returned shape and it does: each record is one planned-sale line, rows carry ticker as received plus current_ticker when the issuer has renamed, and every row carries aggregate_market_value_check with its enumerated meanings. It also flags the estimate nature of both aggregate_market_value and approximate_sale_date and their divergence from the later Form 4. For a 9-parameter, no-output-schema read tool this is as complete as an agent could need.

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 baseline is 3, but the description adds genuine semantics the schema lacks: min_value interacts with NULLs ('Null never satisfies min_value and sorts last'), and ticker matching returns rows filed under former symbols and carries current_ticker, while querying a retired symbol returns only rows filed under it. It also warns that sort_by=aggregate_market_value needs the check field filtered to 'checked'. The remaining parameters (limit, since/until, filer_name, company_cik) get no added 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?

The description states a specific verb and resource: 'Returns Form 144 filings — notices of proposed sale by corporate insiders ... under Rule 144'. It explicitly contrasts itself with the closest sibling, get_insider_transactions ('that tool tells you what insiders just did, this one tells you what they're about to do'), so an agent can route between the two without opening either schema. The only weakness is placement — the purpose sentence sits behind a long ticker-semantics preamble — but the content itself is unambiguous.

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 enumerates concrete triggering intents: 'insiders who have announced they're about to sell, upcoming insider sales at a specific company, large planned sales by value, or which executives are signaling intent to exit positions.' It names the alternative tool and the condition that selects it (forward-looking Form 144 vs. completed Form 4), and notes the filing thresholds (≥5,000 shares OR ≥$50,000) that bound when this data even exists. Nothing relevant 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.

get_private_placementsA
Read-only
Inspect

Returns SEC Form D filings — Reg D / Rule 506 private placement offering notices. Use this when the user asks about: who's raising private capital right now, new VC fund formations, private equity raises, real-estate syndicates, hedge fund launches, who's claiming Rule 506(b) vs 506(c) exemption, or to identify directors / executive officers of newly-formed entities. ⚠ total_amount_sold, min_investment_accepted, total_number_already_invested, sales_commissions and finder_fees are NULLABLE — a Form D that did not state a figure reports null rather than 0. The distinction matters here more than anywhere: a Form D filed at the START of an offering legitimately reports $0 sold, so 0 and null mean genuinely different things. Rows stored before 2026-08-17 cannot tell you which they were. Null never satisfies min_amount_sold and sorts last. Source: SEC EDGAR full-text search + per-filing primary_doc.xml. All Reg D filings (504 / 506(b) / 506(c)) plus Section 4(a) exempt offerings flow through here. Form D must be filed within 15 days of the first sale. Each record carries: issuer entity (name, CIK, address, jurisdiction of incorporation, entity type), offering data (industry group, investment fund type for pooled funds, total offering / sold / remaining, minimum investment, federal_exemptions claimed), filing metadata (file_date, date_of_first_sale, is_amendment), and a related_persons[] array of directors / executive officers / promoters. Federal exemption codes (federal_exemptions array): 06b — Rule 506(b) (no general solicitation; up to 35 non-accredited) 06c — Rule 506(c) (general solicitation OK; all accredited) 04(2) — Section 4(a)(2) (statutory private placement) 3C — ICA Section 3(c) (3(c)(1), 3(c)(5), 3(c)(7) etc. — common for funds) 3C.1 — ICA 3(c)(1) (up to 100 investors) 3C.7 — ICA 3(c)(7) (qualified purchasers only) Common industry_group_type values: 'Pooled Investment Fund' (with investment_fund_type='Venture Capital Fund' | 'Private Equity Fund' | 'Hedge Fund' | 'Other Investment Fund') 'Technology', 'Real Estate', 'Health Care', 'Energy', 'Financial Services', 'Manufacturing', 'Other'. Direct filing_id lookup is fastest (accession number). Substring filters on issuer_name, industry_group_type, investment_fund_type, and jurisdiction_of_inc enable topic-style queries. Combine federal_exemption + min_amount_sold for 'who's raising real money under 506(c)' analyses.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNodate_of_first_sale lower bound (YYYY-MM-DD inclusive).
untilNodate_of_first_sale upper bound (YYYY-MM-DD inclusive).
sort_byNoDefault: file_date (most recently filed first).
filing_idNoEDGAR accession number (e.g., '0002131143-26-000001'). Direct doc lookup, fastest.
issuer_cikNoIssuer's SEC CIK (1-10 digits; we zero-pad internally).
sort_orderNoDefault: desc.
issuer_nameNoCase-insensitive substring against the issuer's filed entity name. NOTE: matched over a recent-filing window, so it reliably finds CURRENT filers but can miss an issuer whose Form D filings are older than that window. To pull a specific issuer's full filing history regardless of date, use issuer_cik (most reliable).
is_amendmentNoWhen set, restricts to D/A amendments (true) or original D filings (false). Default: both.
issuer_stateNoIssuer's state (2-letter code, e.g., 'CA', 'NY', 'DE'). Note many funds incorporate in DE while operating elsewhere.
min_amount_soldNoMinimum total_amount_sold (USD). Filters out trivial offerings — use 1000000 for 'real raises'.
federal_exemptionNoFilter to filings claiming a specific exemption code via array-contains. Common: '06b' (506(b)), '06c' (506(c)), '3C.1', '3C.7'.
industry_group_typeNoSubstring against the top-level industry classification (e.g., 'technology', 'real estate', 'pooled investment').
jurisdiction_of_incNoSubstring against state of incorporation (e.g., 'delaware', 'cayman').
investment_fund_typeNoSubstring against the fund subtype, populated when industry_group_type is 'Pooled Investment Fund' (e.g., 'venture capital', 'private equity', 'hedge').

TDQS

A4.6/5.0
Behavior5/5

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

Goes well beyond the readOnly/openWorld annotations: it warns that total_amount_sold, min_investment_accepted, total_number_already_invested, sales_commissions and finder_fees are nullable, explains why 0 vs null differ (a filing at the start of an offering legitimately reports $0), notes pre-2026-08-17 rows cannot distinguish them, states null never satisfies min_amount_sold, and discloses the data source and the 15-day filing rule.

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 purpose, then use cases, then a nullability warning, source, record shape, and code tables — a logical order. It is long, but for a 15-parameter domain-heavy tool most sections (exemption code legend, null semantics) carry information the schema does not, so little is pure filler.

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 15 optional parameters, no output schema, and a complex regulatory domain, the description compensates by enumerating the returned record structure (issuer, offering, filing metadata, related_persons[]), filter interactions, and data caveats. An agent has everything needed to call and interpret results correctly.

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 real meaning the schema lacks — decoding federal exemption codes (06b/06c/04(2)/3C/3C.1/3C.7) and enumerating common industry_group_type and investment_fund_type values, which the schema only hints at. It does not fully re-specify every filter, but the semantic enrichment is genuine.

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 up front ('Returns SEC Form D filings — Reg D / Rule 506 private placement offering notices') and scopes it against adjacent tools by noting that all Reg D filings plus Section 4(a) exempt offerings flow through here (implying Reg A/crowdfunding do not). An agent can identify this tool 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?

Offers an unusually rich when-to-use list (private capital raises, VC fund formations, PE raises, real-estate syndicates, hedge fund launches, 506(b) vs 506(c)) plus concrete query strategy ('direct filing_id lookup is fastest', 'combine federal_exemption + min_amount_sold'). It lacks explicit exclusions or named alternative sibling tools (e.g., get_reg_a_offerings), 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.

get_product_recallsA
Read-only
Inspect

Returns safety recalls from federal agencies — drug recalls (FDA), medical device recalls (FDA), food/dietary supplement recalls (FDA), and (coming in v1A.1) vehicle recalls (NHTSA) and consumer-product recalls (CPSC). Use this when the user asks about: recent recalls for a specific company or product, FDA Class I (most severe) recalls, active vehicle recalls by make/model, food contamination recalls, drug shortages and recalls, or to add a 'product-safety event' flag to insider activity / 8-K filings / enforcement actions. Sources (filter via the source enum): fda_drug — openFDA /drug/enforcement.json. Drug recalls including prescription, OTC, biologics. Class I/II/III severity. fda_device — openFDA /device/enforcement.json. Medical device recalls (implants, diagnostics, equipment, software). Same classification scheme. fda_food — openFDA /food/enforcement.json. Food + dietary supplements. Pathogen contamination, allergen mislabeling, etc. cpsc — saferproducts.gov RestWebServices/Recall. Consumer-product recalls (clothing, electronics, toys, batteries, etc.). No severity classification; classification field is null. nhtsa — Vehicle, tire, equipment, child-seat recalls. Deferred to v1A.1 (api.nhtsa.gov bulk endpoint pending investigation). Cross-source pairing pattern: Recall → 8-K Item 7.01/8.01: pair with get_material_events Recall → insider sells: pair with get_insider_transactions Recall → SEC/DOJ follow-on: pair with get_enforcement_actions Recall → company filings: pair with get_proxy_filings (DEF 14A risk factors) Each record is one recall. Identifier format: {source}-{recall_number} (e.g., 'fda_drug-D-1234-2026'). FDA classifications: Class I — serious adverse health consequence or death Class II — temporary or reversible health consequence Class III — unlikely to cause adverse health consequence Source freshness (per-source publication cadence, not KeyVex bug): CPSC publishes within ~1-2 days; recent data flows hourly-fresh. openFDA's snapshot updates every ~10-14 days, and each snapshot carries recall_initiation_date values that LAG the snapshot date by another 30-45 days (the time between FDA classifying a recall and openFDA exposing it). Net: FDA records in this collection typically run ~4-6 weeks behind real-world recall dates, while CPSC is current. A default desc-by-date sort therefore looks CPSC-heavy at the top even when FDA matters more for the query. Filter by source='fda_*' to see FDA-only and avoid the skew. classification filter scope: 'classification' is an FDA-only field. CPSC records always have classification=null (CPSC doesn't use the FDA severity scheme). Filtering by classification excludes ALL CPSC rows by definition. The query response surfaces this with a notice in coverage_warning when the filter is set.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum records to return. Default 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only recalls whose recall_initiation_date is on or after this date.
untilNoISO date (YYYY-MM-DD). Only recalls whose recall_initiation_date is on or before this date.
sourceNoFilter to a single agency / category. Omit to see all sources combined.
statusNoExact match. Common values: 'Ongoing', 'Completed', 'Terminated', 'Recall Initiated'.
sort_byNoDefault: recall_initiation_date.
sort_orderNoDefault: desc (most recent first).
vehicle_makeNoNHTSA-only filter. Vehicle make, uppercase (e.g., 'TOYOTA', 'FORD'). Ignored for other sources.
recall_numberNoRecall identifier as filed (e.g., FDA 'D-1234-2026'). Combine with source for direct doc lookup, fastest path.
vehicle_modelNoNHTSA-only filter. Case-insensitive substring against vehicle model. Ignored for other sources.
classificationNoFDA severity classification. Class I is most severe (death / serious harm). Ignored for NHTSA / CPSC records.
recalling_firmNoCase-insensitive substring against the recalling firm name (e.g., 'Pfizer', 'Toyota', 'Whole Foods').
product_descriptionNoCase-insensitive substring against the product description (e.g., 'lithium', 'romaine', 'airbag').

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare read-only/open-world/non-destructive, and the description adds substantial behavior beyond them: per-source publication cadence, the ~4-6 week FDA lag that skews default date sorts, the fact that classification filtering excludes all CPSC rows and surfaces a coverage_warning, and NHTSA being deferred to v1A.1. This is exactly the kind of operational context an agent needs and cannot get from structured fields.

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 purpose is front-loaded in the first sentence and the body is organized into clearly labeled sections (source breakdown, pairing pattern, classification scheme, freshness, filter scope). It is long, but the length is largely earned by 13 parameters and five heterogeneous sources; only the 'coming in v1A.1' caveats and per-source repetition could be trimmed.

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 no output schema, the description carries the return-value burden and does so partially: it states each record is one recall, defines the identifier format, explains the classification scheme, and flags the coverage_warning. It stops short of describing the full record shape or pagination behavior, which is the only remaining gap.

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 genuinely extends several parameters: it explains what each `source` enum value maps to (openFDA endpoints, CPSC service), clarifies that `classification` is FDA-only and excludes CPSC, documents the `{source}-{recall_number}` identifier format, and notes `vehicle_make` is uppercase NHTSA-only. It adds little beyond the schema for the self-explanatory filters (limit, sort_by, status), keeping it short of a 5.

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 ('Returns safety recalls from federal agencies') and enumerates the exact recall categories covered. It is clearly distinguishable from siblings like get_drug_adverse_events, get_fda_approvals, and get_enforcement_actions, which cover different datasets.

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?

Provides an explicit 'Use this when the user asks about...' list covering company/product recalls, Class I severity, vehicle recalls, food contamination, and flagging insider/8-K/enforcement activity. It also names concrete alternatives (get_material_events, get_insider_transactions, get_enforcement_actions, get_proxy_filings) with the pairing conditions, so routing is unambiguous.

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

get_proxy_filingsA
Read-only
Inspect

Returns Schedule 14A proxy filings — the document public companies send shareholders ahead of annual or special meetings. Each record is one filing carrying executive compensation tables, board nominations, shareholder proposals, auditor info, and voting matters. Use this when the user asks about: executive compensation, board elections, shareholder proposals, M&A votes, proxy contests, auditor changes, say-on-pay outcomes, or upcoming annual meetings. Coverage: the full DEF 14A family back to 2016 for the US public-company universe (sourced from EDGAR's complete quarterly full-index); a daily feed keeps it current. Rows are tagged with a company's PRIMARY common ticker — for dual-class issuers (e.g. GOOGL/GOOG, BRK-A/BRK-B) query by company_cik to retrieve every share class in one shot. Filing types (the four-form DEF 14A family): DEF 14A — Definitive proxy (the annual-meeting filing) DEFA14A — Additional materials (supplements to a prior DEF 14A) DEFM14A — Merger-related proxy (filed when shareholders vote on M&A) DEFR14A — Revised definitive proxy (amendments to a prior DEF 14A) Convenience flags derived from filing_type: is_merger_related — true for DEFM14A is_amendment — true for DEFR14A is_additional_materials — true for DEFA14A period_of_report population (IMPORTANT for filtering / sorting): - Recent-window rows (filed ~2024-onward via the daily feed / per-ticker pull): DEF 14A primaries ~100% populated (meeting/record date); DEFA14A/DEFM14A/DEFR14A typically EMPTY (correct-as-filed — SEC's submissions API leaves those reportDate fields blank). - Historical backfilled rows (the bulk of 2016-2024 depth, sourced from EDGAR's full-index): period_of_report is EMPTY for all form types — the index carries no report date. - Bottom line: filter/sort by filing_date for chronological queries; period_of_report is not reliably present across the collection. v1A is metadata-only: ticker, company name, CIK, filing type, dates, primary document URL. The proxy body is not extracted in v1. primary_document_url points agents at the source HTML for direct fetch when they need exec comp tables or proposal text.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoDefault 50, max 500.
sinceNoISO date (YYYY-MM-DD). Only records on or after this date.
untilNoISO date (YYYY-MM-DD). Only records on or before this date.
tickerNoStock symbol filter, e.g. 'AAPL'. Case-insensitive.
sort_byNoDefault filing_date.
sort_orderNoDefault desc.
company_cikNoSEC CIK number (10-digit, padded). Alternative to ticker.
filing_typeNoExact filing-type filter. Use 'DEFM14A' for M&A-vote proxies only, 'DEF 14A' for annual proxies only.
is_amendmentNoConvenience flag: filter to DEFR14A (revised) only.
is_merger_relatedNoConvenience flag: filter to DEFM14A only.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint, openWorldHint, destructiveHint=false), yet the description adds substantial non-obvious behavior: coverage starts 2016, period_of_report is systematically empty for most form types and unreliable for sorting, v1A is metadata-only with the proxy body unextracted, and primary_document_url is the escape hatch to the source HTML. This is exactly the extra context annotations cannot supply.

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, then usage triggers, then coverage caveats — a sensible order and every block is actionable. It is long, however, and the bulleted filing-type glossary partially restates enum values already present in the schema, so it is thorough rather than maximally 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?

No output schema exists, so the description carries the return-value burden itself and does: it lists the returned metadata fields (ticker, company name, CIK, filing type, dates, primary document URL) and states plainly that the proxy body is not extracted. For a 10-parameter tool with zero required params and no output schema, nothing essential is missing.

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?

Schema coverage is 100% (baseline 3), but the description goes well beyond it: it defines each DEF 14A family member, explains the convenience flags, warns that sort_by='period_of_report' is unreliable and filing_date should be preferred, and tells the agent that ticker is primary-class-only while company_cik retrieves every share class. These are semantics the enum values alone do not convey.

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 precise verb+resource ('Returns Schedule 14A proxy filings') and immediately defines what a proxy filing is, so the agent can distinguish it from the many sibling SEC-filing tools (insider, NPORT, tender offers, comment letters). The scope — public-company shareholder meeting documents — is unambiguous.

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 enumerates trigger scenarios (executive compensation, board elections, shareholder proposals, M&A votes, proxy contests, auditor changes, say-on-pay, annual meetings) and gives selection guidance for alternatives within the tool (use filing_type='DEFM14A' for M&A only; query by company_cik instead of ticker for dual-class issuers).

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

get_reg_a_offeringsA
Read-only
Inspect

Returns SEC Form 1-A filings — Regulation A+ 'mini-IPO' offering statements, 2015-06→present: companies raising up to $20M (Tier 1) or $75M (Tier 2) from the public without a full IPO. One record per filing with the issuer (SIC code, jurisdiction, year incorporated, employees, city/state), tier election, offering terms (security types, count, price, total aggregate amount, estimated net), service providers WITH FEES (underwriter, sales commissions, auditor, legal), and the issuer's summary financials from Part I (cash, assets, liabilities, equity, revenues, net income). Use this when the user asks about: Reg A / Reg A+ raises, mini-IPOs, small- cap capital formation, who's underwriting or auditing small offerings, or issuer financials before a raise. form family: '1-A' initial | '1-A/A' amendment | '1-A POS' post-qualification amendment (is_post_qualification) | -W withdrawals (is_withdrawal, metadata-level). One offering typically chains 1-A → 1-A/A… → qualification → 1-A POS updates — filter cik + sort asc to read it. Coverage (honest): the offering-statement family only. The Reg A+ periodic reports — 1-K annual (with actual proceeds raised), 1-SA semiannual, 1-Z exit — use different schemas and are a planned separate dataset. Offering circulars (253G) are prose documents — follow filing_index_url. Pure-publisher posture: issuer-reported Part I numbers as filed, parsed by KeyVex.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoIssuer CIK (any zero-padding).
tierNoTier election: Tier1 (≤$20M, state review) or Tier2 (≤$75M, preempts state review).
limitNoMaximum filings. Default 50, max 500.
sinceNoFiling date lower bound (YYYY-MM-DD inclusive).
untilNoFiling date upper bound (YYYY-MM-DD inclusive).
sort_orderNoSort by filing date. Default desc.
issuer_nameNoCase-insensitive substring against issuer name.
jurisdictionNoIssuer's jurisdiction of organization (two-letter, e.g. 'DE').
accession_numberNoDirect lookup by EDGAR accession number.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare read-only, open-world, and non-destructive. The description adds valuable context beyond that: data provenance ('issuer-reported Part I numbers as filed, parsed by KeyVex'), honest coverage limits ('the offering-statement family only'), and detailed record contents (issuer, tier, offering terms, service providers with fees, financials). This goes well beyond the annotation baseline.

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 long but well-structured with clear segments (purpose, when to use, form family, coverage, posture) and front-loaded with the core function. Every sentence contributes useful information, though some details could be trimmed for brevity without losing meaning.

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?

No output schema exists, so the description must explain return values—and it does thoroughly: it enumerates the record fields (issuer, tier election, offering terms, service providers with fees, Part I financials). It also covers coverage boundaries and chaining behavior, making it complete for an agent to call and interpret results correctly.

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 the baseline is 3. The description adds parameter usage guidance beyond the schema: it explains how to read a chained offering ('filter cik + sort asc') and mentions the tier parameter semantics (Tier 1 vs Tier 2 limits) in context, providing extra value for invocation.

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 ('Returns') and resource ('SEC Form 1-A filings — Regulation A+ mini-IPO offering statements') with scope dates and tier distinctions. It clearly differentiates from siblings like get_crowdfunding_offerings (Reg CF) and get_registration_statements (S-1 etc.) through precise terminology and field coverage.

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 lists when to use ('Use this when the user asks about: Reg A / Reg A+ raises, mini-IPOs, small-cap capital formation, who's underwriting or auditing small offerings, or issuer financials before a raise') and when not to use (periodic reports 1-K/1-SA/1-Z are a separate dataset; offering circulars are prose documents to follow via filing_index_url). It also gives chaining guidance ('filter cik + sort asc to read it').

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

get_registration_statementsA
Read-only
Inspect

Returns SEC Form S-1 / S-3 / S-3ASR registration statements — securities offering registrations filed with the SEC. Use this when the user asks about: which companies are going public (IPO pipeline via S-1), shelf registrations (S-3 / S-3ASR — company registers securities to sell over multiple offerings without re-registering; large established issuers use the automatic S-3ASR variant), recent secondary offerings, registration amendments updating prior filings, or to bridge from a company name / ticker to the prospectus prose. Forms covered: S-1 — Initial registration (IPO + first-time registrants) S-1/A — Amendment to an S-1 S-3 — Shelf registration (issuers meeting reporting / market-cap criteria; lets them issue securities over time without re-registering each time) S-3/A — Amendment to an S-3 S-3ASR — Automatic shelf registration. The shelf form used by Well-Known Seasoned Issuers (large established companies like Apple, Ford, most of the S&P 500). Effective on filing. These issuers file S-3ASR, NOT plain S-3. Source: SEC EDGAR full-text search. Returns one record per filing, deduped by accession. Exhibit attachments (EX-10, opinion letters, fee tables, etc.) are filtered out — only the canonical form types are returned. v1A is metadata only. Each record has filer name + CIK + optional ticker + SEC file_number, state, SIC code(s), and URLs. Substantive prospectus content (offering size, share counts, use of proceeds, risk factors, financial statements) lives at primary_document_url — agents follow for the prose. SCOPE — covers S-1 (IPO), S-3 + S-3ASR (shelf, including WKSI auto shelves), plus /A amendments. S-8 employee-benefit-plan registrations, S-4 merger/acquisition registrations, and F-series foreign-issuer forms are NOT ingested. 424B prospectus supplements (offering takedowns off an existing shelf) are out of scope — query the shelf registration itself. Amendment chains: all amendments share the same sec_file_number as the original. Use sec_file_number filter to fetch an entire amendment chain. Pure-publisher posture: KeyVex doesn't derive 'likely-to-IPO' or 'price-target' signals from registration filings.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNofile_date lower bound (YYYY-MM-DD inclusive).
untilNofile_date upper bound (YYYY-MM-DD inclusive).
s1_onlyNoWhen true, restricts to S-1 family (S-1 + S-1/A) — the IPO / first-time pool.
s3_onlyNoWhen true, restricts to S-3 family (S-3 + S-3/A + S-3ASR) — the shelf pool, including automatic shelf registrations filed by Well-Known Seasoned Issuers.
filer_cikNoFiler's SEC CIK (1-10 digits).
filing_idNoEDGAR accession number. Direct doc lookup.
filer_nameNoCase-insensitive substring against the filer's entity name (e.g., 'kraneshares', 'karyopharm'). NOTE: matched over a recent-filing window, so it reliably finds CURRENT filers but can miss an issuer whose registrations are older than that window. To pull a specific issuer's full registration history regardless of date, use filer_cik (most reliable) — e.g. Circle Internet Group is filer_cik 0001876042.
sort_orderNoDefault: desc (most recently filed first).
filing_typeNoExact filing-type match.
filer_tickerNoTicker symbol (e.g., 'KPTI'). Often empty for IPO-stage S-1 filers (they don't have a ticker yet).
sec_file_numberNoSEC-assigned registration file number ('333-XXXXXX'). Stable across amendments — use to fetch a full amendment chain.
exclude_amendmentsNoWhen true, drops /A amendments. Default false.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly/openWorld/destructive=false, and the description adds substantial context beyond that: records are metadata-only in v1A, deduped by accession, exhibit attachments (EX-10, opinion letters, fee tables) are filtered out, substantive content lives at primary_document_url, and the publisher does not derive IPO-likelihood or price-target signals. That is real behavioral disclosure, not restatement.

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, then triggers, then scope — a good ordering. It is long, but 13 parameters and a five-form taxonomy justify much of the length; the per-form glossary is somewhat verbose and partially duplicates the filing_type enum descriptions, which costs a point.

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 no output schema, the description carries the return-shape burden and does: one record per filing, deduped, filer name + CIK + optional ticker + file_number, state, SIC codes, and URLs, with primary_document_url as the follow-on target. Scope, taxonomy, and amendment behavior are all covered.

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. The description earns above baseline by explaining cross-parameter semantics: amendments share one sec_file_number so that filter retrieves a full chain, and it repeats the filer_name recent-window caveat with filer_cik as the reliable fallback. Some of this overlaps the schema text, but the amendment-chain workflow adds genuine 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+resource (SEC Form S-1/S-3/S-3ASR registration statements) and immediately narrows it with explicit boundaries: S-8, S-4, F-series are NOT ingested and 424B supplements are out of scope. An agent can distinguish this from get_private_placements, get_reg_a_offerings, get_proxy_filings, and get_sec_comment_letters 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 Guidelines5/5

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

Gives explicit user-intent triggers ('which companies are going public', 'shelf registrations', 'bridge from a ticker to the prospectus prose') and explicit exclusions (S-8/S-4/F-series, 424B takedowns — query the shelf itself). It also routes the agent to sec_file_number for amendment chains, which is an alternative-path instruction.

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

get_roll_call_votesA
Read-only
Inspect

Returns congressional roll-call vote metadata (House + Senate) from api.congress.gov. Use this when the user asks about: recent votes in either chamber, votes on a specific bill, votes by date range, or to chain to per-member positions via the source_data_url. Sources: api.congress.gov v3 for House votes; senate.gov XML (legislative/LIS/roll_call_lists/) for Senate votes — joined into one collection. Captures roll-call (recorded) votes only — voice votes and unanimous-consent passages aren't roll calls and don't appear here. v1A returns vote-level metadata: chamber, roll call number, vote type, result, the legislation being voted on (linked via bill_id), and links to the Clerk's authoritative XML data. Per-member positions (yea/nay/present/not voting per bioguide_id) live in the XML at source_data_url; agents fetch that directly when they need member detail. v1.1 will add a separate roll_call_member_votes tool/ collection for queryable per-member positions. Vote identifiers are stable composite keys: '{chamber}-{congress}- {session}-{rcNumber}', e.g., 'house-119-1-240' or 'senate-119-1-15'. Common vote_type values: 'Yea-And-Nay' (regular recorded vote), '2/3 Yea-And-Nay' (suspension of rules, requires 2/3 majority), 'Recorded Vote', 'Quorum'. Common result values: 'Passed', 'Failed', 'Agreed to', 'Rejected', 'Motion Agreed To', 'Motion Failed'. When a vote is on a bill, legislation_type + legislation_number are populated and bill_id is set to the composite key — use that to join to get_bills. For procedural votes (motion to recommit, motion to adjourn, etc.), those fields may be empty. Amendment + Senate detail: House votes ON AN AMENDMENT carry amendment_number, amendment_author (sponsor + label), and amendment_type (e.g. 'HAMDT'). Senate votes carry vote_title (descriptive title — e.g. a confirmation or motion), measure (the specific measure a question references, e.g. 'S.Amdt. 5740'), and en_bloc_matters[] (one {issue, question, result} per matter when a batch of nominations is decided en bloc). All are empty / [] where not applicable.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum votes to return. Default 50, max 500.
sinceNoVote-start date lower bound (ISO YYYY-MM-DD inclusive).
untilNoVote-start date upper bound (ISO YYYY-MM-DD inclusive).
resultNoSubstring match against result text (e.g., 'passed', 'failed', 'agreed').
bill_idNoFilter to votes on a specific bill (composite key like '119-HR-134'). Use to chain a bill lookup → votes on that bill.
chamberNoFilter to House or Senate roll calls.
sort_byNoDefault: start_date (most recent votes first).
vote_idNoComposite vote identifier ('{chamber}-{congress}-{session}-{rcNumber}', e.g., 'house-119-1-240'). Direct doc lookup, fastest path.
congressNoCongress number (e.g., 119).
sort_orderNoDefault: desc.
session_numberNoSession within the Congress. Session 1 = first calendar year of the Congress; Session 2 = second year.
legislation_typeNoFilter to votes on a specific legislation type.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations declare readOnlyHint/openWorldHint/destructiveHint=false, and the description goes well beyond that: it discloses the two upstream sources (api.congress.gov v3 and senate.gov XML), the join into one collection, what is excluded (non-recorded votes), what v1A returns vs. what a future v1.1 tool will add, and where per-member positions live. This is unusually rich 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-loaded with purpose and usage before diving into metadata details, which is good structure. However it is quite long and includes some enumerations (vote_type/result values) that border on redundancy for a schema that already documents parameters.

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 no output schema, the description carries the burden and does so: it enumerates the returned metadata fields (chamber, roll call number, vote type, result, legislation link, XML links) and explains amendment/Senate-specific fields. An agent has everything needed to call and interpret results.

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 value by explaining the vote_id composite key pattern, that bill_id is a join key to get_bills, and that legislation fields are empty for procedural votes. It reinforces but doesn't fully supersede the schema's own parameter docs.

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 ('Returns congressional roll-call vote metadata (House + Senate)') and clearly distinguishes itself from siblings like get_bills and get_member_profile by scoping to vote-level data. The composite key format and chamber scope make it unmistakable.

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 enumerates when to use it ('recent votes in either chamber, votes on a specific bill, votes by date range') and when not ('voice votes and unanimous-consent passages aren't roll calls and don't appear here'). It also names the chaining path to get_bills and clarifies that per-member detail requires fetching source_data_url rather than this tool.

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

get_screening_listA
Read-only
Inspect

Returns entries from the US Consolidated Screening List (CSL) — the combined feed of twelve federal export-screening lists. Use this when the user asks about: whether a company or person is on a US screening / sanctions / denied-party list (KeyVex republishes the lists; it is not a screening service), BIS Entity List members, Military End User designations, or to add a 'restricted party' flag to a federal contractor or foreign agent. The CSL unifies twelve lists (filter via source_short): SDN — Specially Designated Nationals (Treasury/OFAC) EL — Entity List (Commerce/BIS) DPL — Denied Persons List (Commerce/BIS) MEU — Military End User List (Commerce/BIS) UVL — Unverified List (Commerce/BIS) CMIC — Non-SDN Chinese Military-Industrial Complex Companies (Treasury) CAP — Capta List (Treasury) DTC — ITAR Debarred (State) ISN — Nonproliferation Sanctions (State) MBS — Non-SDN Menu-Based Sanctions List (Treasury) PLC — Palestinian Legislative Council List (Treasury) SSI — Sectoral Sanctions Identifications List (Treasury) Broader than get_ofac_sdn — the SDN list is just one source here. For the OFAC-SDN deep view use get_ofac_sdn; to search every US list at once use this tool. Cross-source pairing: pair with get_federal_contracts to flag a contractor that also appears on a screening list, and with get_foreign_agents for the foreign-entity overlay. Each record carries name + alt_names, the source list, sanctions programs, addresses, distinct countries, and identification documents.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoCase-insensitive substring matched against the entry name AND its alternate names / aliases.
typeNoFilter by entry type.
limitNoMaximum records to return. Default 50, max 500.
countryNoISO-2 country code (e.g. 'CN', 'RU', 'IR'). Matches entries with an address in that country, or where the source list assigns the entry itself to that country. Common spellings are accepted ('UK', 'Turkiye', 'PRC', 'DPRK'); an unrecognised code is rejected rather than returning an empty result.
programNoCase-insensitive substring against the entry's sanctions / control programs.
sort_byNoDefault: name.
sort_orderNoDefault: asc (alphabetical by name).
source_shortNoFilter to one source list by short code: SDN, EL, DPL, MEU, UVL, CMIC, CAP, DTC, ISN, MBS, PLC, SSI.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true and destructiveHint=false, so safety is covered. The description still adds real behavioral context the annotations cannot: KeyVex 'republishes the lists; it is not a screening service', which tells the agent not to treat results as an authoritative screening determination. It also enumerates the returned record fields, though it says nothing about pagination or result-size limits.

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 usage triggers are front-loaded in the first sentence, and the sibling routing sits at the end where it is easy to find. The twelve-list enumeration is long but each entry is a compressed code-plus-name pair rather than prose, so it earns its space as a decode table.

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?

There is no output schema, but the description compensates by describing what each record carries ('name + alt_names, the source list, sanctions programs, addresses, distinct countries, and identification documents'). Combined with the source-code legend and cross-tool pairing notes, an agent has everything needed to call this correctly.

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 the baseline is 3, but the description goes beyond it by expanding the source_short codes into their full list names (SDN = Specially Designated Nationals/Treasury, EL = Entity List/Commerce, MEU, UVL, CMIC, etc.), which the schema only lists as bare codes. That mapping genuinely helps the agent pick the right filter 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?

The opening sentence gives a specific verb and resource ('Returns entries from the US Consolidated Screening List') and immediately scopes it as the combined feed of twelve federal lists. It explicitly contrasts itself with the sibling get_ofac_sdn ('Broader than get_ofac_sdn'), so an agent can distinguish the two 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?

Concrete trigger phrases are listed ('whether a company or person is on a US screening / sanctions / denied-party list', 'BIS Entity List members', 'Military End User designations'), and the alternatives are named with their selecting conditions: get_ofac_sdn for the SDN deep view, get_federal_contracts and get_foreign_agents for cross-source pairing.

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

get_sec_comment_lettersA
Read-only
Inspect

Returns SEC comment-letter correspondence: form UPLOAD (the SEC's letter TO the company — the questions) and CORRESP (the company's response). The Division of Corporation Finance sends these during filing reviews; they're released ~20+ business days after the review closes. Coverage 2005→present. Use this when the user asks about: whether a company is (or was) under SEC review, accounting-quality red flags before they become enforcement, the back-and-forth around an IPO registration, or to pair with fundamentals / insider activity ('were insiders selling while the SEC was asking questions?'). Reading a thread: filter by ticker or cik, sort date_filed asc — a review is an alternating UPLOAD/CORRESP chain; the final short UPLOAD is typically the 'review complete' letter. v1A is metadata-only: follow filing_index_url for the letter text. released_date is set on records captured from EDGAR's daily indexes (the dissemination day); older backfilled records carry only date_filed (the letter's own date) — dissemination day isn't recoverable historically and KeyVex never fabricates it. A comment letter is ROUTINE, not an accusation — most large filers get reviewed on a cycle (Sarbanes-Oxley §408 requires review at least every 3 years). Signal comes from thread LENGTH, topic, and recency, which agents judge from the letter text. Pure-publisher posture: EDGAR index records as published.

ParametersJSON Schema
NameRequiredDescriptionDefault
cikNoSEC CIK (any zero-padding).
formNoUPLOAD = SEC's letter to the company; CORRESP = the company's response.
limitNoMaximum letters to return. Default 50, max 500.
sinceNoLetter date lower bound (YYYY-MM-DD inclusive).
untilNoLetter date upper bound (YYYY-MM-DD inclusive).
tickerNoExact ticker (resolved from CIK; '' for unlisted filers).
sort_orderNoDefault desc. Use asc with a ticker filter to read a review thread in order.
company_nameNoCase-insensitive substring against the company name as indexed.
accession_numberNoDirect lookup by EDGAR accession number (e.g., '0000000000-26-004788').

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnly, openWorld, non-destructive), and the description still adds substantial context beyond them: coverage 2005→present, ~20+ business day release lag, v1A metadata-only with filing_index_url for text, released_date semantics for backfilled records, and a 'never fabricates' integrity note.

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 form definitions, then usage, then reading mechanics and caveats. It is fairly long, and the sort/thread guidance slightly overlaps the sort_order schema description, but nearly every sentence carries distinct operational 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 no output schema and 9 optional parameters, the description fully compensates: it explains what is returned (metadata vs. letter text via filing_index_url), the release timing model, historical coverage, and the interpretative limits (signal from thread length/topic/recency). 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?

Schema coverage is 100%, so the baseline is 3, but the description goes further by explaining how to combine filters (filter by ticker or cik, sort date_filed asc) and how to interpret the resulting alternating UPLOAD/CORRESP chain. It adds thread-reading semantics not 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?

States a specific verb and resource ('Returns SEC comment-letter correspondence') and immediately defines the two form types UPLOAD and CORRESP. An agent can distinguish this from siblings like get_enforcement_actions or get_registration_statements 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?

Explicitly enumerates when to use it: 'whether a company is (or was) under SEC review, accounting-quality red flags before they become enforcement, the back-and-forth around an IPO registration,' and pairing with fundamentals/insider activity. Also explains the practical reading workflow (filter by ticker/cik, sort asc, interpret the alternating chain).

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

get_sec_fails_to_deliverA
Read-only
Inspect

Returns SEC Fails-to-Deliver (FTD) rows — daily settlement failures by ticker / CUSIP / date. Each row is one ticker on one settlement date where a clearing-member's short sale FAILED to deliver shares. Signal value: persistent FTDs are a contrarian short-squeeze leading indicator. When the daily FTD quantity spikes on a ticker, it often means naked short pressure overwhelming locate supply or settlement / locate mechanism breaking down. The Reg SHO Threshold Securities list (FTDs > 0.5% of issued shares for 5+ consecutive days) is a derived view; this tool exposes the underlying daily data. Source: SEC bi-monthly cnsfails<a|b>.zip files at sec.gov/files/data/fails-deliver-data/. Published ~1 week after each half-month settlement period. Coverage: every U.S.-listed security with a recorded settlement failure during the period. Killer query patterns: - Daily FTD history for a ticker: ticker='GME' + sort_by='settlement_date' - Largest FTDs this month: min_value=1000000 + sort_by='fail_value' - Squeeze setup candidates: min_quantity=100000 + recent dates - Look-up by CUSIP: cusip='B6S7WD106' (foreign issuers, complex names) Derived field: fail_value = quantity_fails × price (dollar magnitude of the failure on that day). Reference price comes from the SEC's posted value at settlement. Note: FTDs are bi-monthly batch-published, not real-time. SEC releases each half-month batch (cnsfailsa = days 1-15, b = 16-end) roughly 2-4 weeks AFTER that half-month period closes, so the most recent settlement date can be 2-4 weeks behind today (e.g. in mid-June the latest published batch is first-half-May, with settlement dates through ~May 15). That apparent lag is the SEC publish cadence, not a KeyVex freshness gap.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoDirect doc lookup ({YYYY-MM-DD}-{cusip}). Fastest path.
cusipNoExact CUSIP (preferred for foreign issuers / class shares).
limitNoMax records. Default 50, max 500.
sinceNoInclusive lower bound on settlement_date (YYYY-MM-DD).
untilNoInclusive upper bound on settlement_date (YYYY-MM-DD).
tickerNoTicker symbol (uppercased automatically).
sort_byNoSort key. Default: settlement_date.
min_valueNoInclusive lower bound on fail_value (dollars). E.g., 1000000 surfaces only $1M+ failures.
sort_orderNoDefault: desc.
min_quantityNoInclusive lower bound on quantity_fails (shares). E.g., 100000 surfaces only large failures.

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the annotations (readOnlyHint/openWorldHint/destructiveHint=false), the description discloses non-obvious behavioral facts an agent would otherwise get wrong: bi-monthly batch publication, the cnsfails<YYYYMM>a/b split, the 2-4 week publish lag, and an explicit warning that apparent staleness is SEC cadence rather than a freshness bug. It also defines the derived fail_value field and its reference price.

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 front-loaded: purpose, then row semantics, then signal value, source, coverage, query patterns, then caveats. It is long and the 'Signal value' interpretation (naked short pressure, locate mechanism breakdown) is arguably padding for a retrieval tool, but the structure is clean and each remaining sentence carries usable 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 10-parameter, zero-required, no-output-schema tool, the description covers source, publication cadence, coverage universe, row grain, derived fields, and concrete query recipes. An agent has everything needed to select filters, sort correctly, and interpret freshness without a return-value 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 real meaning the schema lacks: it defines fail_value = quantity_fails × price and its reference-price source, and gives worked examples for min_value and min_quantity thresholds plus when to prefer cusip over ticker. It stops short of documenting id/since/until/limit/sort_order beyond what the schema already says.

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 verb+resource ('Returns SEC Fails-to-Deliver (FTD) rows — daily settlement failures by ticker / CUSIP / date') and immediately scopes what one row means (one ticker on one settlement date). It is clearly distinguishable from the many sibling datasets (insider filings, institutional holdings, etc.) because it pins the exact SEC dataset and grain.

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 provides explicit 'Killer query patterns' with concrete parameter combinations for each intent (daily history, largest FTDs this month, squeeze candidates, CUSIP lookup), which is strong when-to-use guidance. It does not, however, name an alternative tool (e.g. unified_search) or state when this tool should be avoided, so it stops 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.

get_tender_offersA
Read-only
Inspect

Returns SEC Schedule TO filings — public tender offer disclosures. Use this when the user asks about: who's bidding to acquire company X, what M&A offers are in flight, share buyback announcements, amendments to existing tender offers (price increases / extensions), or to pair with 13D activist stakes for the 'stake → bid' story. Source: SEC EDGAR full-text search. Forms covered: SC TO-T (third- party tender offer — someone outside the company bidding for shares), SC TO-T/A (amendments), SC TO-I (issuer tender offer — company buying back its own shares), SC TO-I/A (issuer amendments). v1 returns filing metadata only — bidder + target + form type + filing date + URL. Offer price, shares sought, and expiration date live inside the HTML attachment at primary_document_url; agents follow that URL to read the substantive terms. Amendment filings share the same target/bidder/file_number as the original offer; use file_number to group an amendment chain. Pure-publisher posture: KeyVex does not derive 'likely to close' or 'expected premium' signals. The data here is what was filed, no more.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum filings to return. Default 50, max 500.
sinceNoFiling date lower bound (ISO YYYY-MM-DD inclusive).
untilNoFiling date upper bound (ISO YYYY-MM-DD inclusive).
form_typeNoExact form match. Useful for narrowing to amendments only ('SC TO-T/A') or original offers only ('SC TO-T').
bidder_cikNoBidder's SEC CIK. Find all tender offers by a particular acquirer.
sort_orderNoDefault: desc (most recent filings first).
target_cikNoTarget's SEC CIK (10-digit zero-padded). Use when ticker is ambiguous (multiple share classes).
bidder_nameNoCase-insensitive substring against bidder_name. Bidders in SC TO-T are often private SPVs ('2025 Acquisition Company, LLC') — use this to find them by issuer / parent name.
issuer_onlyNoWhen true, restricts to SC TO-I family (issuer buybacks). Default false.
target_nameNoCase-insensitive substring against target_name. Useful when ticker isn't known (e.g., private companies in TO-T filings).
target_tickerNoTarget company ticker (e.g., 'KZR'). For SC TO-T this is the company being bid for; for SC TO-I this is the company buying back its own shares (target == bidder).
accession_numberNoEDGAR accession number (e.g., '0001140361-26-020397'). Direct doc lookup, fastest path.
third_party_onlyNoWhen true, restricts to SC TO-T family (third-party offers). Default false.
exclude_amendmentsNoWhen true, drops /A amendment filings. Default false (amendments included).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only cover the safety profile (readOnly, non-destructive, openWorld). The description adds substantial behavioral context beyond them: v1 returns filing metadata only, substantive terms (price, shares sought, expiration) live in the HTML at primary_document_url, amendments chain via file_number, and a stated no-derivation 'pure-publisher' posture.

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 usage, then form taxonomy, then output limitations. Dense and largely earned, though the form-type parentheticals and the closing posture sentence add some length that could be trimmed without losing signal.

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 no output schema, the description must explain the return shape, and it does so precisely: metadata fields returned (bidder, target, form, date, URL) versus terms deferred to the attachment. A 14-parameter, zero-required tool is fully covered.

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 the schema carries the parameter burden (baseline 3). The description still adds interpretation beyond it — e.g., grouping amendment chains via file_number, the target==bidder relationship for SC TO-I, and SPV bidder naming in SC TO-T — which meaningfully guides filtering choices.

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 ('Returns SEC Schedule TO filings — public tender offer disclosures') and enumerates the exact form types covered (SC TO-T, SC TO-T/A, SC TO-I, SC TO-I/A) with plain-language glosses. It explicitly distinguishes itself from siblings by naming the 13D activist-stakes tool it pairs with.

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?

Provides an explicit 'Use this when the user asks about...' list covering bidder identification, in-flight M&A offers, buybacks, and amendments, plus the compound 'stake → bid' workflow with get_activist_stakes. An agent can route to this tool from a user question without inference.

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

get_treasury_auctionsA
Read-only
Inspect

Returns Treasury security auctions — Bills (≤1yr), Notes (2-10yr), Bonds (20-30yr), TIPS (inflation-protected), and FRNs (floating-rate). Each record is one CUSIP issuance with announcement metadata + post- auction results. Key signal fields agents care about: - bid_to_cover_ratio: demand. >2.5 strong, <2.0 weak. - high_yield / average_yield: market clearing rate. - direct_bidder / indirect_bidder breakdowns: domestic vs foreign demand. - soma_holdings + soma_included: Fed System Open Market Account allocation. A live measure of Fed QE/QT activity on each issue. Records have a two-stage lifecycle: announcement (results fields null) → post-auction (full results populated). Idempotent saves on cusip + auction_date overwrite cleanly when results publish. Security types: 'Bill', 'Note', 'Bond', 'TIPS', 'FRN', 'CMB' (cash- management bill). Use security_type filter to focus on one term group. Note: Treasury reports TIPS and FRNs under security_type Note/Bond with an inflation-indexed / floating-rate flag (not as their own type); filtering security_type:'TIPS' or 'FRN' here resolves to those flags for convenience.

ParametersJSON Schema
NameRequiredDescriptionDefault
cusipNoFilter to one specific CUSIP issuance.
limitNoDefault 50, max 500.
sinceNoISO date YYYY-MM-DD. Applied to sort_by field.
untilNoISO date YYYY-MM-DD.
sort_byNoDefault auction_date.
reopeningNoFilter to reopenings (new tranches of an existing CUSIP) only when true.
sort_orderNoDefault desc.
security_typeNoe.g. 'Bill', 'Note', 'Bond', 'TIPS', 'FRN', 'CMB'.
min_bid_to_coverNoFilter to auctions with bid_to_cover_ratio >= this value (e.g. 2.5 for strong-demand auctions only).
min_offering_amountNoFilter to auctions with offering_amount >= this dollar amount.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnly/openWorld/destructive, so the safety profile is covered. The description adds meaningful behavior beyond that: a two-stage lifecycle where results fields are null until post-auction, idempotent saves keyed on cusip + auction_date, and the TIPS/FRN flag-resolution quirk.

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 purpose and organizes the rest into scannable bullet groups. It is on the longer side and the signal-field list could be trimmed, but each section carries distinct information rather than restating the schema.

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 10-parameter read tool with no output schema, the description does the heavy lifting: it explains the record shape, key return fields, lifecycle states, and filter quirks. Only the absence of explicit sibling routing keeps it from being fully complete.

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 genuine meaning on top: it explains that security_type:'TIPS'/'FRN' resolve to inflation-indexed/floating-rate flags rather than native types, and gives interpretation thresholds for bid_to_cover_ratio.

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?

States a specific verb and resource ('Returns Treasury security auctions') and enumerates the covered instrument classes (Bills, Notes, Bonds, TIPS, FRNs). It does not explicitly name or contrast against a sibling, so it falls just short of the top band.

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?

Offers practical guidance on filtering ('Use security_type filter to focus on one term group') and interprets signal fields, but never states when to choose this tool over alternatives or any exclusion conditions. Usage context is implied rather than explicit.

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. 64 tool updates
    • First observedget_activist_stakes
    • First observedget_aircraft_registry
    • First observedget_alerts
    • First observedget_annual_financial_disclosures
    • First observedget_bank_financials
    • First observedget_bills
    • First observedget_cftc_cot_reports
    • First observedget_company_profile
    • First observedget_congressional_trades
    • First observedget_consumer_complaints
    • First observedget_corporate_patents
    • First observedget_crowdfunding_offerings
    • First observedget_daily_prices
    • First observedget_delistings
    • First observedget_drug_adverse_events
    • First observedget_economic_indicators
    • First observedget_enforcement_actions
    • First observedget_epa_enforcement
    • First observedget_fda_approvals
    • First observedget_fec_candidate_profile
    • First observedget_fec_contributions
    • First observedget_fec_disbursements
    • First observedget_fec_independent_expenditures
    • First observedget_federal_contracts
    • First observedget_federal_grants
    • First observedget_federal_register_documents
    • First observedget_fema_disasters
    • First observedget_ferc_filings
    • First observedget_foreign_agents
    • First observedget_fund_holdings
    • First observedget_fundamentals
    • First observedget_government_publications
    • First observedget_h1b_filings
    • First observedget_insider_filings
    • First observedget_insider_holdings
    • First observedget_insider_transactions
    • First observedget_institutional_holdings
    • First observedget_intraday_quote
    • First observedget_investment_advisers
    • First observedget_lobbying_filings
    • First observedget_lobbyist_contributions
    • First observedget_material_events
    • First observedget_member_profile
    • First observedget_money_market_funds
    • First observedget_nlrb_cases
    • First observedget_nonprofit_filings
    • First observedget_nport_filings
    • First observedget_ofac_sdn
    • First observedget_oig_exclusions
    • First observedget_open_payments
    • First observedget_osha_enforcement
    • First observedget_planned_insider_sales
    • First observedget_private_placements
    • First observedget_product_recalls
    • First observedget_proxy_filings
    • First observedget_reg_a_offerings
    • First observedget_registration_statements
    • First observedget_roll_call_votes
    • First observedget_screening_list
    • First observedget_sec_comment_letters
    • First observedget_sec_fails_to_deliver
    • First observedget_tender_offers
    • First observedget_treasury_auctions
    • First observedunified_search

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    A
    maintenance
    Lets AI assistants query Congress and corporate insider trading data, including who is buying, ticker scores, and whether those signals performed.
    11
    1
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    Wall Street data feed for AI agents, providing access to 100M+ source-traced SEC records, institutional holdings, insider trades, congress trading, and more via MCP tools.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables querying US congressional and executive stock trading disclosures, including recent trades, top movers, and individual member activity, with filters and performance analytics.
    453 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Self-hosted financial data terminal for AI agents. Scrapes and serves SEC filings (full-text search), 13F institutional holdings, insider and congressional trades, FINRA short data, FRED economic indicators, CFTC futures positioning, VIX/put-call ratios, and daily stock prices over MCP.
    230
    AGPL 3.0
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources