Skip to main content
Glama

Taokeh MCP server

Server Details

Taokeh is accounting software for Malaysian SMEs — double-entry books, LHDN e-Invoice (MyInvois), SST, and full statutory payroll — and this connector opens a company's live books to the AI its owner already uses.

59 tools. The reads answer real questions from the ledger: P&L and balance sheet with server-computed comparisons, cash position, A/R and A/P aging, per-channel marketplace sales, an 8-week cash-flow forecast, tax position, document search with e-Invoice standing, and a one-call daily brief. The writes are drafts only — expenses, invoices, bills, quotes, purchase orders, receipts, credit and debit notes, adjusting journals, bank-statement imports and bank-row suggestions — every figure re-checked by the server, every draft waiting for a human tap in Taokeh. The AI can also work the Shoebox: staff snap paper on free phone logins, and the connector lists the pile, reads each photo, and files the draft with the original attached — the server maps its own stored copy, so the document trail stays byte-perfect.

One connection is bound to one company at consent; no tool takes a company argument. Migrating from another system? The same connector stages the chart of accounts, opening balances, contacts, products, historical documents and workspace settings onto the owner's own review screens. Bring your own AI subscription — no per-call fees.

Ownership verified
Status
Healthy
OAuth
Works in Glama
Last Tested
Transport
Streamable HTTP
URL

TDQS

A4.1/5.0

Scored across 64 tools

Disambiguation5/5

Every tool targets a distinct resource and action, and the descriptions actively steer the agent to the right sibling (e.g. ar_aging vs open_invoices, create_credit_note_draft vs create_debit_note_draft vs update_invoice_draft, bank_review_queue vs payer_history). No two tools have genuinely blurry boundaries.

Naming Consistency5/5

All tool names are snake_case and follow predictable families — create_*_draft, update_*_draft, search_*, resolve_*, stage_*, get_* — while read-only reports are named by their subject (balance_sheet, ar_aging, cash_position). The pattern is consistent and easy to navigate.

Tool Count2/5

At 64 tools this is well past the 25+ threshold and far above the typical 3–15 well-scoped range. The broad accounting domain justifies a large surface, but the set is too heavy for one server and would be more coherent split into books, banking, payroll, and migration modules.

Completeness4/5

Core accounting lifecycles are thoroughly covered: quotes→invoices→credit/debit notes, bills→payments, bank import→review→classification, payroll reads, stock reads, migration, and all major reports. Minor gaps exist — no buy-side debit-note lane, no delivery-order creation, no stock-adjustment tool, and only resolve-by-name contact/product lookup — but agents can work around them.

Available Tools

64 tools
ap_agingA/P agingA
Read-only
Inspect

Whom you owe money and how overdue it is — your accounts-payable aging by supplier.

ParametersJSON Schema
NameRequiredDescriptionDefault
asOfNo

TDQS

A4.1/5.0
Behavior4/5

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

The annotations already declare readOnlyHint=true, and the description complements this by explaining the report's structure (grouped by supplier, with aging/overdue information). No contradiction exists, and the description adds behavioral context about what the report presents beyond the safety hints.

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

Conciseness5/5

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

The description is a single, memorable sentence with an effective em-dash structure. It is front-loaded with a relatable question and wastes no words.

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

Completeness4/5

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

The tool is simple: one optional parameter, no output schema, and safety annotations provided. The description explains what the report contains (payables aging by supplier). The only gap is the lack of clarification around the 'asOf' parameter, but for a simple report this is a minor omission.

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

Parameters2/5

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

The description does not mention the only parameter 'asOf' at all. Since schema description coverage is 0%, the description fails to compensate for the lack of parameter explanation. The parameter name and pattern are somewhat self-explanatory, but the description adds no semantic value for how the date affects the aging report.

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 specifies the exact resource ('accounts-payable aging by supplier') and the informational content ('whom you owe money and how overdue it is'). It clearly distinguishes itself from the sibling tool 'ar_aging' by explicitly naming the accounts payable side.

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 provides clear context for when to use the tool: when you need to understand outstanding payables and their overdue status. It does not explicitly name alternatives, but the 'accounts-payable' phrasing versus the sibling 'ar_aging' implies the differentiation, and no exclusions are needed.

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

ar_agingA/R agingA
Read-only
Inspect

Who owes you money and how overdue it is — accounts-receivable aging across ALL customers, bucketed by age. For the unpaid invoices of ONE named customer, use open_invoices.

ParametersJSON Schema
NameRequiredDescriptionDefault
asOfNo

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already indicate readOnlyHint=true, so the description adds value by explaining the output is bucketed by age and spans all customers. It does not mention return format, but that is not required given the read-only nature and no output schema. No contradiction with annotations.

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

Conciseness5/5

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

The description is two sentences, front-loaded with a clear question and purpose, and includes a direct pointer to an alternative. Every sentence earns its place with no 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 a simple read-only report with one optional parameter and no output schema, the description covers the core purpose and when to use it. However, it omits explaining asOf, which is a minor completeness gap. Overall, it is sufficient for tool selection.

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

Parameters2/5

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

Schema description coverage is 0%: the only parameter 'asOf' is not explained in the description. The description never mentions that an optional as-of date can be provided, leaving the agent to infer its meaning from the name and pattern. This is a notable gap.

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

Purpose5/5

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

The description clearly states the tool generates an accounts-receivable aging report across ALL customers, bucketed by age. It uses a specific verb and resource ('accounts-receivable aging') and distinguishes itself from the sibling tool open_invoices, which targets a single customer.

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 explicitly provides an alternative: 'For the unpaid invoices of ONE named customer, use open_invoices,' guiding when to use this tool vs. another. It also implies the scope is all customers, making the usage context clear.

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

balance_sheetBalance sheetA
Read-only
Inspect

Your balance sheet as of a date: assets, liabilities and equity, with the balanced check. ONE EQUITY LINE IS NOT AN ACCOUNT: Current Earnings, whose code is an em-dash rather than an account number, is the profit to date — revenue minus expenses over every entry up to asOf — folded into equity so the sheet balances. Nothing posts to it, it has no ledger of its own, and there is no year-end close in these books, so it runs back to the company's first entry rather than restarting each January; it equals the income_statement net income over the same end date. Never describe it as an account, never offer to open its ledger, and never treat it as a missing or mis-coded row. COMPARISON (optional): a balance sheet is a POSITION AT A DATE, not a period — so unlike income_statement its comparison is ONE DATE against ANOTHER DATE, never two ranges. Set compare to 'previous_month_end', 'previous_year_end' or 'same_date_last_year', OR give an explicit earlier date as compareAsOf. You get both positions in full plus, per account line and per total, deltaCents and deltaPct computed server-side in integer cents — the movement in that balance BETWEEN the two dates. deltaPct is NULL whenever the earlier balance is zero (a percentage change from zero is undefined — say "no comparable base", never ∞% or 100%), and percentages are measured against the ABSOLUTE earlier balance. points gives both dates, how many days apart they are, and whether either is today or later (still open, so the balances can move); notes states the basis in plain words, including a warning if either sheet does not balance. Never describe the gap between the two dates as a 'period' figure: these are two positions, and the delta is the movement between them.

ParametersJSON Schema
NameRequiredDescriptionDefault
asOfNo
compareNoNamed comparison POINT (a single earlier date, not a range). Omit for no comparison.
compareAsOfNoAn explicit earlier date to compare the position against (overrides `compare`).

TDQS

A4.8/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses important behavior: deltas are computed server-side in integer cents, deltaPct is NULL when earlier balance is zero, percentages use absolute earlier balance, current earnings is not a real account, nothing posts to it, and warnings are included if the sheet does not balance. This is detailed behavioral transparency.

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 quite long and repeats the position-versus-period warning multiple times, but the repetition is purposeful to prevent common misinterpretations. It is well structured with clear sections for comparison semantics, delta behavior, and output notes, so the length is mostly justified.

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?

Even though there is no output schema, the description fully explains output concepts: deltaCents, deltaPct, points, notes, null handling, and warning behavior. It also covers edge cases like zero earlier balances and imbalanced sheets, making it complete for an agent to invoke and interpret the result.

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

Parameters4/5

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

The description adds strong semantic value for compare and compareAsOf, including override behavior and the meaning of named comparison points. However, asOf has no schema description and the description does not state what happens when asOf is omitted, even though it is not required in the schema. It mostly compensates for schema gaps but leaves that minor ambiguity.

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

Purpose5/5

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

Description clearly states the tool returns a balance sheet as of a date: assets, liabilities, equity, and the balanced check. It also distinguishes itself from income_statement by emphasizing position vs period, so an agent can tell it apart from key siblings.

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

Usage Guidelines5/5

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

The description explicitly explains when the comparison mode is appropriate, how to choose named comparison points versus an explicit earlier date, and warns against framing the delta as a period figure. It names income_statement as the contrasting tool and gives clear 'never' instructions, acting as practical usage guidance.

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

bank_reconciliation_statusBank reconciliation statusA
Read-only
Inspect

Where each bank account stands on reconciliation: the GL balance against the latest statement's closing balance (with the difference, or an honest "unknown" when a statement carries no balance figure), the row counts by status (SUGGESTED = something proposed a category and it is waiting on the owner; UNCATEGORIZED = nothing ever put a category on it, which covers both the imported rows nothing matched and every row the owner typed in by hand; CONFIRMED = categorised but not yet in the ledger; POSTED = in the ledger; IGNORED = deliberately set aside), the unreviewed backlog, and — per recent statement — the opening/closing balances, the arithmetic tie-out result and its status counts. A CREDIT CARD account reconciles here too and its figures are NOT cash: a card's balance is a liability, so a negative figure means money still OWED on the card — never report it as cash held. These are the SAME figures the in-app Bank Reconciliation page shows. READ-ONLY: categorizing, confirming and posting rows are human actions in Taokeh.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already mark readOnlyHint=true, and the description adds valuable behavioral nuance beyond that: the credit card liability warning, the 'unknown' handling when a statement has no balance, and the explicit note that categorizing/confirming/posting are human actions. This gives an agent important context not encoded in the schema.

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 dense and somewhat long, but each sentence carries meaningful content: position wording, exact fields reported, the credit card liability distinction, parity with the web UI, and the read-only boundary. No fluff, though it 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?

With no output schema, the description carries the needed completeness load: it names the report contents, the status categories, the backlog, the per-statement balances, and the warning about credit card figures. An agent has enough understanding to call the tool and interpret a returned snapshot.

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

Parameters4/5

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

The tool has zero parameters and schema coverage is 100%, so the schema already exhaustively documents the input contract. Description therefore does not need to compensate for missing parameter documentation. Baseline 4 is appropriate.

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

Purpose4/5

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

The description clearly identifies a read-only bank reconciliation status report: GL balance versus latest statement closing balance, status counts, and per-statement tie-out. It is specific about the resource and scope, although it does not explicitly differentiate itself from sibling tools like bank_review_queue.

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

Usage Guidelines3/5

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

The description establishes clear context: it shows the same figures as the in-app Bank Reconciliation page and is READ-ONLY, implying it is for checking status, not taking action. However, it never explicitly says when to choose this over alternatives or names a sibling like bank_review_queue for the actionable side.

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

bank_review_queueBank review queueA
Read-only
Inspect

The IMPORTED BANK REGISTER — the rows that came in on a bank or card statement, in ANY status, defaulting to the ones still awaiting review. By default (no status) it is exactly the unreviewed queue it has always been: the unposted rows of one statement, or of the latest imported statement if you don't name one. Pass status to read the settled history instead — 'confirmed' (categorised, not yet posted), 'posted' (in the ledger), 'ignored' (the owner set them aside) or 'all'. Pass from/to WITHOUT a statementId to read a DATE WINDOW across every statement this company has imported, rather than one statement; the payload then says scope:'window' and statement is null. A window holding more than 1000 rows still awaiting review is refused with the count — narrow the dates or name a statementId; settled history has no such ceiling. ⛔ HAND-RECORDED settlements are NEVER here whatever you pass: a receipt or supplier payment typed into Taokeh by hand has no statement behind it, and this tool is the imported register only. To find those, use search_documents with docType:'payment'. Each row still awaiting review carries Taokeh's LIVE suggested category + contact, a confidence score (0–1) and a plain-language reason, computed the SAME way the in-app Banking → Review screen computes them. A suggestion does NOT come only from the tenant's transaction history: the owner can write a standing RULE for a payer (What Taokeh has learned → Bank rules), and such a rule beats what Taokeh worked out on its own — those rows' reasons read "You set this rule on " rather than "Learned: … (×N)". If a suggestion looks unlike the payer's history, the rule is usually why; say so instead of calling the history wrong. Sorted lowest-confidence first (the ones that need a human eye), capped at 200 with an honest truncation note, plus per-confidence bucket counts so you can say e.g. "46 are mechanical, 13 need eyes". A row can also carry possibleDuplicateOf: a receipt or supplier payment the owner already recorded BY HAND that looks like the same money as this imported line (same account, same amount, within three days) — it is only a resemblance, Taokeh decides nothing from it, and you should say so rather than propose a category for money that may already be in the books. What you CAN do with a row: review it, explain it, and PROPOSE a category with draft_bank_classification — and, for the two categories whose account the owner picks by hand (OTHER and INTERNAL_TRANSFER), the LEDGER ACCOUNT too. Your proposal is written to the row as an "AI suggestion" the owner sees on Banking → Review, with your proposed account pre-selected in their dropdown and marked as yours; rows already carrying a proposal from you come back here as yourProposal, so you can see what you told them. What you can NEVER do: CONFIRM or POST a row — and proposing the account changes nothing about that: it fills a dropdown, the owner still clicks. Accepting a category and posting each line is always a human click in Taokeh; hand the owner the review link. (Since 2026-08-19 the owner can also accept Taokeh's confident suggestions, and post confirmed lines, from the /go command bar's approval deck — still one human tap either way. YOUR OWN proposals are accepted only on Banking → Review, where your reasons are shown.) ⚠ SETTLED ROWS CARRY NO SUGGESTION. A row that has already been confirmed, posted or ignored comes back with suggestedCategory, suggestedContact, confidence, reason and possibleDuplicateOf all NULL — the classifier is not re-run over decided history, because a fresh guess printed beside a decision the owner already made reads as a second opinion on settled books. Those rows carry what was actually DECIDED instead: category, glAccount ({code,name}, null if the row has none), contact (the customer or supplier on the row), journalEntryId (null unless posted), splits (where the amount was divided across accounts) and allocations (the invoices or bills the money settled). statusCounts always reports how the rows in scope break down by status.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest transaction date (YYYY-MM-DD).
fromNoEarliest transaction date (YYYY-MM-DD). WITHOUT a statementId, from/to widen the read to a DATE WINDOW across every imported statement — 'what did the bank register show in July' rather than 'what is on this one statement'.
statusNoWhich rows: 'unreviewed' (DEFAULT — everything not yet posted or ignored, i.e. the review queue), 'confirmed', 'posted', 'ignored', or 'all'. Only unreviewed rows carry suggestions; the rest carry what was decided.
statementIdNo

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already mark readOnlyHint: true, and the description adds substantial behavioral detail beyond that: the 1000-row window ceiling with refusal, the 200-row cap with truncation note, null suggestions on settled rows, possibleDuplicateOf being only a resemblance, and the rule that confirmation/posting always requires human action. There is no contradiction with the read-only annotation; the tool only reads, while proposals are made through another 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 long and dense, but it is front-loaded with the core purpose, uses visual markers like ⛔ and ⚠, and structures the content around defaults, windows, exclusions, suggestions, and settled rows. Some phrases are repetitive or contain asides that could be trimmed, but the length is largely justified by the number of modes and caveats an agent must understand.

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 explaining return semantics. It covers scope and statement fields, statusCounts, confidence buckets, row-level fields for both unreviewed and settled rows, possibleDuplicateOf, yourProposal, truncation behavior, and the refusal condition for large windows. Combined with the explicit routing to sibling tools, this is enough for an agent to invoke the tool 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 75% and the schema's statementId description is corrupted, so the description must compensate and largely does. It explains the meaning and default of status, the date-window behavior of from/to without statementId, and the role of statementId in scoping and the row cap. The description adds real semantics beyond the schema, though statementId itself is not given a dedicated, direct definition.

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

Purpose5/5

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

The description clearly identifies the tool as the imported bank register/review queue and explains that it returns statement rows in any status, defaulting to unreviewed ones. It differentiates itself from search_documents for hand-recorded settlements and from draft_bank_classification for proposing categories, so an agent can select it correctly among the many sibling 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?

The description gives explicit selection criteria: use the default for the unreviewed queue, pass status for settled history, pass from/to without statementId for a date window, and use search_documents with docType:'payment' for hand-recorded entries. It also states what the tool can and cannot do, naming draft_bank_classification as the separate tool for proposals.

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

business_snapshotBusiness snapshotA
Read-only
Inspect

A one-glance health check of your business: today's and this-month's sales and expenses, so far. Sales and expenses ONLY — if you want the fuller morning read (cash position, who owes you, pending approvals, tax position, low stock) call daily_brief instead; it includes everything here.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, so safety is covered. The description adds scope context ('Sales and expenses ONLY', 'so far') which clarifies what data is returned without contradicting the read-only nature. It doesn't exhaustively describe edge cases but does enough for a simple read tool.

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

Conciseness5/5

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

The description is two sentences with no wasted words. It front-loads the core purpose and then delivers a clear alternative, making every sentence earn 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 zero-parameter tool with no output schema, the description fully explains what the tool returns and how it relates to sibling tools. There is no missing context for an agent to invoke 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?

The tool has zero parameters, so the baseline is 4 per rubric. The description compensates by explaining exactly what data is included (today's and this-month's sales and expenses), which adds meaning beyond the empty 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 clearly states it provides a one-glance health check of today's and this-month's sales and expenses, which is a specific verb+resource. It also explicitly differentiates from the daily_brief sibling tool by limiting scope to sales and expenses only.

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

Usage Guidelines5/5

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

The description explicitly names the alternative tool (daily_brief) for a fuller morning read and states that it includes everything this tool provides, effectively giving when-to-use and when-not-to-use guidance. This is exemplary usage differentiation.

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

cash_forecastCash-flow forecastAInspect

A forward 8-week cash-flow forecast — honest arithmetic from your books, not a model. Opening position is your LIQUID balances right now (cash + bank accounts + gateway clearing); money the owner has advanced to the business is a liability, not cash, so it is excluded — the assumptions list says so. Inflows are your OPEN customer invoices scheduled at their due dates; already-overdue receivables are NOT assumed collected — they are reported separately as overdueArCents (upside, stated honestly). If a sales channel is connected and reports money earned but not yet paid out (TikTok Shop's unsettled orders), that pool comes back SEPARATELY as channelUnsettled (amount, count, currency, and the date it should land, 14 days out — the late end of the channel's own settlement window). It is the channel's own ESTIMATE, so it is deliberately NOT counted into any week, any closing balance or the dip: a warning about cash running low must never be weakened by money that is not in the books. Treat it as stated upside, exactly like overdueArCents. If no channel is connected, the channel add-on has lapsed, or its API cannot be reached, the field is absent and the forecast is unchanged. Outflows are your open supplier bills (at bill date — Taokeh does not store supplier terms yet), payroll (estimated from your last finalized run: net pay + employer EPF/SOCSO/EIS on payday), PCB/EPF/SOCSO/EIS remittances (15th of the following month), loan installments (estimated from the last recorded installment), and SST payable at its return due date if you're SST-registered. Returns week-by-week inflows/outflows/closing balance, the dip (the lowest projected closing — when and how deep cash runs lowest), and an assumptions list spelling out every estimate. All amounts are integer CENTS (RM = cents ÷ 100).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

The description goes well beyond the sparse annotations, disclosing that values are estimates, what happens when channel data is unavailable or the API fails, that estimates are deliberately not counted in the dip, and that amounts are integer cents. It also explains the 'assumptions' list and the treatment of owner advances as liabilities, making the tool's behavior highly transparent.

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 and dense, but nearly every sentence adds necessary domain context: treatment of overdue amounts, channel unsettled pools, payroll components, remittance timing, and units. It is front-loaded with the core purpose and then expands into behavioral specifics. It could be tighter with bulleted structure, but the verbosity is justified by the tool's complexity.

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?

Even without an output schema, the description fully covers return values (week-by-week inflows/outflows/closing balance, dip, assumptions list), units, data sources, and edge cases such as disconnected or lapsed channel access. It is complete enough for an agent to invoke the tool 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?

The input schema is empty, so the baseline for parameter semantics is 4. There are no parameters to document; the description instead explains the forecast's inputs implicitly from the books. No additional parameter-level detail is needed beyond what the empty schema already conveys.

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

Purpose5/5

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

The description clearly identifies this as an 8-week cash-flow forecast built from bookkeeping data, with a specific scope: opening liquid balances, scheduled inflows, and known/estimated outflows. It also distinguishes itself from related reporting tools by emphasizing it is 'not a model' and by explaining what is deliberately excluded or reported separately.

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 strong context for when to rely on this forecast: it states what is included, what is excluded (owner advances, overdue receivables, unsettled channel money), and how to treat those exclusions as stated upside. It does not explicitly name alternative sibling tools or say 'use this when you need X, not Y', but the inclusion/exclusion logic effectively guides selection.

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

cash_positionCash positionA
Read-only
Inspect

How much cash you have right now: every bank account and cash pocket with its current GL balance, plus a grand total. total is LIQUID money only — physical cash + bank accounts + the payment-gateway clearing float — and accounts lists exactly those accounts. Money the OWNER has advanced to the business (the Shareholder Loan) is returned SEPARATELY as ownerFunding: it is a LIABILITY the business owes back, not cash it holds, so it is never inside total and must never be added to it or described as cash. CREDIT CARDS are returned separately for exactly the same reason, as cards (one entry per card, with cardsOwing for the total): what sits on a card is money OWED to the issuer, not cash the business holds, so it is never inside total — report it as card debt beside the cash figure, never as cash and never as a negative bank balance. Each card carries its own direction ('owed_to_issuer', or 'in_credit' when the card is overpaid) — follow it rather than assuming a debt. Balances are MYR-booked (the books are kept in ringgit); a foreign bank account shows its currency label for context, but the balance figure is still the MYR-booked GL balance.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses important behavioral semantics: `total` is strictly liquid cash, owner funding and card balances are separate liabilities, each card has a `direction`, and balances are MYR-booked even for foreign accounts. This is substantial, practical behavior guidance that prevents common misuse and does not contradict 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?

The description is front-loaded with the main numeric/computational answer and then expands into the important exclusions. It is dense and fairly long, but each rule contributes to correct interpretation of the output. A little tightening would improve it, but for a tool with a nuanced cash distinction structure, the length is justified.

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 at all, the description carries the responsibility of defining the return shape, and it does so effectively: `total`, `accounts`, `ownerFunding`, `cards`, `cardsOwing`, `direction`, and the relevant currency/booking behavior are all explained. There is enough detail for an agent to both invoke the tool and correctly present the result.

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?

There are zero parameters and the schema has 100% coverage by being empty, so the baseline of 4 applies. The description adds value by explaining the meaning of the conceptual result fields, but there are no parameter-specific semantics needed here.

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 clearly states what the tool reports: current cash across every bank account and cash pocket, with GL balances and a grand total. Even though it uses a question-style phrasing rather than a firm imperative, it identifies the resource and scope precisely and separates it from forecast-type siblings by focusing on the right-now position.

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

Usage Guidelines4/5

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

The description clearly establishes when this tool is appropriate: whenever the agent needs the current cash position as booked in the GL. It also instructs how to treat returned values, such as reporting owner funding as a liability and card balances only as debt outside total. It does not, however, explicitly name alternatives like cash_forecast or business_snapshot, so it stops short of giving full when-to-use/when-not-to-use routing.

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

channel_summarySales-channel summaryA
Read-only
Inspect

Your sales broken down by CHANNEL (Shopee, TikTok, Shopify, your storefront, …) for a date range. Per channel: the order count, gross goods revenue, seller discounts (e.g. Shopee vouchers), shipping income (buyer-paid shipping), freight-out (what shipping cost you), marketplace fees, and netProceeds — the settlement booked on each sale's own entry: for credit marketplaces (Shopee/TikTok) that is the net A/R payout the channel owes you; for the storefront it is what settled into cash / the gateway clearing account at sale time. RETURNS: returns is the revenue reversed by that channel's credit notes (returns/refunds) in the range — the Sales Returns & Allowances booked on them; netGoodsRevenue = grossGoodsRevenue − returns. The other six figures (grossGoodsRevenue, discounts, shipping, freight, marketplaceFees, netProceeds) are GROSS of returns — they come from the INVOICE side only — so a channel with heavy returns no longer looks inflated. A row appears for every channel with sales OR returns in the range — returns lag sales, so a channel whose only in-range activity is returns still shows (saleCount 0, gross figures 0, its returns, and a negative netGoodsRevenue). (A Shopee-wallet FEE credit note books marketplace fees, not a goods return, so it adds 0 to returns.) A marketplace SETTLEMENT CORRECTION — the payout came in short because the buyer returned or cancelled after the invoice was already booked — is also a credit note approved by the owner against the original invoice, and the invoice side stays as it was booked. Only the GOODS portion of such a correction shows in returns: its fee and shipping components are reclassed to marketplace fees / freight on the credit note's OWN entry, while the per-channel marketplaceFees and freight figures here are read from the INVOICE side only — so a fee-only correction (the common, batched kind) moves neither returns nor marketplaceFees and is not visible in this tool's output at all. Marketplace invoices are therefore not final at import: a channel's figures for a past range can still move as corrections are approved. NOTE: marketplaceFees covers marketplace commission/service fees booked on the sale's own entry; storefront GATEWAY processing fees are booked on separate payout entries and are NOT included per-channel here (so storefront netProceeds is gross of gateway fees). TIKTOK is the one exception, and it is INCLUDED: TikTok reports no per-order fee at import, so its fees (and the freight split out of its settlement) are booked LATER on a separate settlement entry by "Book settlement fees" (journal reference TIKTOK-FEE-). Those are folded into TikTok's marketplaceFees and freightOut here, and the labelled revenue correction on them adjusts its grossGoodsRevenue. ⚠ THE DATE BASIS DIFFERS on that side: settlement entries are matched on WHEN THE SETTLEMENT WAS BOOKED (the journal entry's own date), while sales are matched on sale date — because that is when the cost hits the P&L. So a June TikTok sale whose payout is settled in July puts its goods revenue in June and its fees in July, and a July-only summary can show a tiktok row with saleCount 0 that is purely settled fees. Say which month you are reading, and never describe a channel's fees as final until its payouts are settled. Manual / non-channel sales are excluded. Give from and to as YYYY-MM-DD.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes

TDQS

A4.3/5.0
Behavior5/5

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

The description extensively discloses behavioral traits beyond annotations: returns lag sales, gross figures exclude returns, settlement corrections are invisible, TikTok fees are booked later on a different date basis, and manual/non-channel sales are excluded. This goes far beyond the readOnlyHint annotation.

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

Conciseness3/5

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

The description is extremely long and dense. While it is well-structured with paragraphs and front-loaded with the core purpose, it contains many edge-case elaborations that could be condensed. It is not concise, but each sentence adds substantive detail, balancing thoroughness with 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 the tool's complexity (multiple channels, returns, corrections, TikTok timing, and fee handling), the description is remarkably comprehensive. It covers all relevant edge cases, including returns-only channels, settlement corrections, and the TikTok date basis discrepancy, ensuring the agent has complete context.

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?

The schema already defines from and to as dates with a pattern. The description only adds 'Give from and to as YYYY-MM-DD,' which redundantly repeats the pattern. Since the parameters are simple and fully defined by the schema, the description adds minimal semantic value beyond what is already structured.

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

Purpose5/5

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

The description clearly states the tool reports sales broken down by channel with a specific list of metrics (order count, gross goods revenue, discounts, shipping, freight, marketplace fees, netProceeds). It distinctly differentiates from sibling tools like sales_summary by focusing on channel-level breakdown and specific accounting nuances.

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 provides clear context on when to use it (e.g., for channel breakdowns, date ranges) and important caveats like mentioning the month being read and not calling fees final until settlements. It doesn't explicitly name alternative tools, but the usage context is unambiguous given the sibling list.

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

counter_dayCounter dayA
Read-only
Inspect

The Counter (Kaunter) till's day, for one date (default today, Malaysia time). Returns: the receipt count and voided count, the cash and DuitNow QR totals, the 5-sen cash-rounding total, whether the day is still OPEN or has been CLOSED into the books, the receipt-number range with any voided numbers listed, and separately the sales BILLED ON CREDIT at the till. IMPORTANT — a counter day is NOT in the ledger until it is closed: while status is 'open' these figures are the till's own receipts and NOTHING has posted, so they will not appear in sales_summary, cash_position or income_statement yet, and stock/COGS have not moved either (they move once, at close). Once status is 'closed', saleId names the ONE consolidated cash sale the whole day posted as, and the figures do reconcile to the books. THE ONE EXCEPTION, and it runs the other way: creditSales are the till's "Invoice it" sales, and they POST IMMEDIATELY as ordinary credit invoices (Dr accounts receivable to a named customer, stock moved at the moment of sale). So unlike the drawer takings they ARE already in sales_summary, income_statement, open_invoices and ar_aging even while the day is open — and they are NOT in cashTotal, qrTotal or the close, because no money changed hands. Never add creditSales.total to the cash and QR totals: the drawer holds cash + QR only, and it ties to the sen. cashTotal is the sum of ROUNDED cash receipt totals (what the drawer holds); qrTotal is never rounded — Malaysia's 5-sen rounding applies to cash only. Receipts of RM10,000 or more cannot join a consolidated e-invoice, so each posts as its own sale: consolidatedCount/consolidatedTotal cover only the receipts that joined the day sale, individualCount/individualTotal the rest, and awaitingBuyerCount is how many of those still have no buyer particulars captured. Counter is a paid add-on (RM49/mo); a company without it gets status 'not_available'.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoThe business date, YYYY-MM-DD in Malaysia time. Omit for today.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already indicate read-only behavior, but the description adds extensive non-obvious semantics: open versus closed posting, immediate posting of creditSales, cash-only rounding, RM10,000 e-invoice splitting, and the not_available status for non-subscribers. Nothing contradicts the readOnlyHint annotation.

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

Conciseness4/5

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

The description is long, but nearly every clause covers a distinct semantic risk: posting timing, credit-sales exception, rounding behavior, consolidated invoices, and add-on availability. The first sentence front-loads the tool's purpose, though the emphatic formatting and some repeated caveats keep it from being maximally concise.

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?

Because there is no output schema, the description carries the full burden of explaining return values and field meanings. It covers statuses, saleId, creditSales, cashTotal, qrTotal, consolidation counts, and the paid-add-on not_available case, so an agent has enough context to interpret results and avoid misuse.

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?

The schema already documents the single optional date parameter with a pattern, timezone, and 'omit for today' instruction, so coverage is 100%. The description adds only 'default today, Malaysia time', which largely repeats the schema, so the baseline score of 3 is appropriate.

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

Purpose5/5

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

The description opens with a concrete scope: 'The Counter (Kaunter) till's day, for one date' and enumerates the returned metrics. It also distinguishes this tool from ledger-facing siblings by explaining that open-day figures are not yet in sales_summary, cash_position, or income_statement.

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 explicitly names sibling tools and gives the conditions under which this tool's figures do or do not align with them. It also tells the agent when the tool is the right source for till-level detail versus ledger reports, and warns against summing creditSales into the cash/QR totals.

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

create_bill_draftFile bill draftAInspect

File a supplier-bill DRAFT into Taokeh from a bill you've read. INVENTORY-ONLY — every line must be a product you stock; for services / non-stock / mixed bills use the manual bill form, or create_expense_draft if already paid. This does NOT post to the books — it creates a pending draft the user reviews and approves in Taokeh; only then does it post (receive stock, blend moving-average cost, book input SST as a non-recoverable cost). Shape the fields with intake_contract(doc_type:'bill') + resolve_vendor + resolve_product first. The server re-computes every line quantity from the tally and the grand total — so present your working, but the server's figures are authoritative. READ THE PAYMENT TERM OFF THE BILL and send it as term — a supplier's credit period is what decides when this money actually leaves, so it drives the payables aging buckets, the OVERDUE badge and the 8-week cash forecast; for one of the five preset terms Taokeh fills the due date on the draft itself and shows it on the approval screen. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. If you have the ORIGINAL bill image/PDF, attach it — it rides the draft and lands on the posted bill automatically on approval, so the user never has to re-upload it. Small files: attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
termNoThe SUPPLIER's payment term, exactly as the bill prints it ('Due on Receipt', 'Net 7', 'Net 14', 'Net 30', 'Net 60', or whatever this supplier actually stated — 'COD 7 days', 'Net 45', '30 days EOM'). It is stored as written, so do NOT round a real term to the nearest familiar one. Leave it out when the bill states no term: an unstated term is not 'Due on Receipt', and the bill then simply falls due on its own date.
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a vendor/customer you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
vendorNo
dueDateNoThe due date, YYYY-MM-DD, when the bill states one outright. You usually do not need it: for one of the five preset terms above, Taokeh fills the due date on the draft itself (bill date + 0/7/14/30/60 days) and shows it on the approval screen for the owner to check. State dueDate only to override that, or when the paper gives a due date that does not follow the term. A term Taokeh does not recognise fills NOTHING — if that bill has a due date, say it here, because otherwise the bill falls due on its own date and shows up in the payables aging and the cash forecast a whole credit period early.
vendorIdNo
referenceNo
needsReviewNo
printedTotalNo
purchaseDateYes
paymentMethodYes
shoeboxItemIdNoThe id of a SHOEBOX photo (from shoebox_items) that this draft was read from — the paper someone in the business snapped and sent in. Taokeh attaches ITS OWN stored copy of that photo to the draft, so DO NOT also send the image: no re-upload, no base64, nothing to truncate. Mutually exclusive with attachmentBase64 and attachmentToken. The item must still be waiting: one already booked, set aside, or already carrying a pending draft is refused with the reason. Approving the draft closes that shoebox item against the document it became.
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the posted bill on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL bill as base64 — SMALL files only (a few KB). For a real photo or multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the posted bill on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
confirmNewVendorNoSet to true ONLY after the user has EXPLICITLY confirmed this vendor is genuinely new. It skips the near-miss guard (which rejects a name that looks like shorthand for an existing vendor). Never set it to push a near-miss through — ask the user first.
attachmentFilenameNoOptional original filename for the attachment, e.g. bill.pdf.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the annotations (readOnly=false, destructive=false), the description clearly states this tool does NOT post to the books and only creates a pending draft that the user reviews and approves. It also reveals side effects: the server recomputes quantities, the bill posts later, and attachments ride through to the posted bill.

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 description is dense and information-rich, but very long and repetitive in places, with full paragraphs in ALL CAPS and multiple restatements about due dates, attachments, and terms. It would be more concise if the most essential rules were front-loaded and the repeated cautionary detail trimmed, while still keeping the important edge cases.

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

Completeness5/5

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

Given the tool's complexity and the lack of an output schema, the description covers the full workflow: preparation, line semantics, term handling, review notes, attachment upload paths, size limits, sandbox fallback, and mutual exclusions. An agent has enough context to call the tool correctly and avoid the main failure modes.

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

Parameters4/5

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

The schema already carries detailed descriptions for many high-complexity parameters like term, dueDate, notes, and the attachment fields, and the description adds operational meaning on top of those. A few parameters such as vendorId, reference, and printedTotal receive no extra clarification beyond the schema, but the critical semantic traps are well covered.

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 clear verb and object: 'File a supplier-bill DRAFT into Taokeh from a bill you've read.' It immediately distinguishes this tool from create_expense_draft and the manual bill form, so an agent can tell when this is the right sibling to call.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: inventory-only bills, not services/non-stock/mixed, and not already-paid ones (use create_expense_draft). It also prescribes a preparation pipeline (intake_contract, resolve_vendor, resolve_product), attachment handling, and when to set needsReview.

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

create_contact_draftFile contact draft from a name cardAInspect

File a pending CONTACT draft from a business card YOU have read. Read the card image yourself and pass the fields — personName (required), company, role, phones, emails, address — AND the card image itself, which is REQUIRED: the owner checks your fields against the picture before approving, so a draft without the image cannot be verified and is refused. This does NOT add anyone to the address book: it creates a draft the owner reviews and approves in Taokeh, and only that tap files the contact person (under the company, matched to an existing customer/vendor or created as a new one) with the card image kept on the record. BE HONEST about what you could not read: leave a field EMPTY and say so in notes — never guess a phone digit, an email spelling or a company name. If the photo is blurry, is not a business card, or lists two people, say that in notes and set needsReview. Attach the image with attachmentBase64 + attachmentMediaType (a card photo is usually small enough to inline; send attachmentBytes with it so a truncated base64 is rejected instead of filed), or for a large photo or a PDF use request_attachment_upload → PUT the bytes → pass the returned attachmentToken (never both). Say which side of the book it is with partyKind ('customer' for someone you sell to, 'vendor' for someone you buy from) — default customer — and pass partyName if the user tells you the company is really an existing one under a different spelling. Report the fields back to the user in chat so they can spot a misread before they tap.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoThe person's job title / role as printed, e.g. 'Sales Manager'.
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check against the image before approving — a phone number you could not read cleanly, two people on one card, uncertainty about which line is the company. The reviewer reads this on a small approval card, so keep it brief and human. Leave it empty when there is nothing to flag.
emailsNoThe email addresses printed on the card (up to 3). Never guess a spelling; leave it out and flag it in notes instead.
phonesNoThe phone numbers printed on the card, as printed (up to 3). Leave out any digit-group you cannot read cleanly and say so in notes — a half-guessed phone number is worse than none.
addressNoThe address printed on the card, as one string.
companyNoThe company name printed on the card. Leave it out if the card does not show one.
partyKindNoWhich side of the book the card belongs to: 'customer' (someone you sell to) or 'vendor' (someone you buy from). Defaults to customer.
partyNameNoThe company to file the contact under, when the user tells you it differs from what is printed on the card (e.g. the card shows a brand but the books use the registered name). Omit to use the company printed on the card — the reviewer can still change it before approving.
personNameYesREQUIRED — the person's name exactly as printed on the card. If the name is genuinely illegible, do NOT guess and do NOT file: tell the user the card is unreadable.
needsReviewNoSet true when something about the card gave you pause — a blurry photo, two people on one card, a field you could not read. It flags the draft for the reviewer.
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the image bytes to its uploadUrl. Use this instead of attachmentBase64 for a large photo or a PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The card lands on the created contact on approval, exactly as an inline one does.
attachmentBase64NoThe business-card IMAGE as base64 — REQUIRED (unless you pass attachmentToken). A card photo is normally small enough to inline. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoOptional original filename for the card image, e.g. card.jpg.
attachmentMediaTypeNoThe card image's MIME type, e.g. 'image/jpeg' or 'image/png'. Required when attachmentBase64 is given.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only set flags (readOnlyHint=false, etc.), but the description adds a rich behavioral contract: the image is REQUIRED and a draft without it is refused, blurry/two-person cards must set needsReview, bad files are rejected without filing, and the owner reviews before the contact is added. These details are not captured in 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?

The description is long but each sentence earns its place given the 16-parameter complexity. It is front-loaded with the purpose and required image, then systematically covers workflow, honesty rules, attachment methods, and party handling. It could be structured with bullets for readability, but the density is justified and logically ordered.

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

Completeness5/5

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

For a complex tool with 16 parameters and no output schema, the description covers all essential aspects: purpose, exclusions, behavioral requirements (image required, refusal, needsReview), parameter semantics (attachment options, defaults), and even post-call expectations (reporting fields back to the user). Nothing critical 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?

While schema coverage is 100%, the description adds crucial cross-parameter logic absent from the schema: mutual exclusivity of attachmentBase64 and attachmentToken, the role of attachmentBytes in rejecting truncated uploads, the default of partyKind to 'customer', and the purpose of partyName for existing companies. These are operational semantics that materially affect correct 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?

The first sentence clearly states 'File a pending CONTACT draft from a business card YOU have read,' naming the specific resource (contact draft) and verb (file). It explicitly contrasts with adding to the address book, distinguishing it from sibling draft tools like create_invoice_draft and clearly setting its scope.

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 explains the primary use case (when you have read a business card image) and states what it does NOT do ('This does NOT add anyone to the address book'), providing a clear exclusion. It also routes the agent to request_attachment_upload for large images or PDFs, with an explicit 'never both' rule, giving concrete alternative paths.

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

create_credit_note_draftFile credit-note draftAInspect

File a CREDIT NOTE draft into Taokeh — a sales return, short delivery, price correction or allowance that reduces what a customer owes. This does NOT post to the books: it creates a pending draft the user reviews and approves in Taokeh, and only then does it reduce the customer's balance, reverse the revenue and SST, and (if the user says the goods came back) put stock back. Shape the fields with intake_contract(doc_type:'credit_note') first. RESOLVE THE ORIGINAL INVOICE FIRST: a credit note is issued AGAINST an invoice — find it with search_documents and pass its id as originalDocId with kind:'against_invoice'. Only a credit with NO source invoice is kind:'allowance', and an allowance is never linked to an invoice, never capped by one, inherits no SST codes and never restocks — so do not file a real return as one; ask the user which invoice it is against. Send all amounts POSITIVE (Taokeh stores the credit note negative itself). A line can only credit back as MANY units as that invoice actually sold, net of earlier credit notes — an over-quantity line is refused naming what is left, so read the invoice's own unit of measure rather than converting it (1 carton is not 100 pieces). Whether goods physically came back into stock is the USER's decision at approval — goodsReturned is only a hint that pre-ticks their checkbox on the full review page, and a one-tap approval always posts money-only. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check) for any doubt. Filed it wrong? Use revise_draft (kind: 'credit_note') rather than filing a second one. IS A CREDIT NOTE EVEN THE RIGHT DOCUMENT? Only when something CHANGED AFTER the sale — goods came back, a price was renegotiated, a discount was agreed later. If the sale simply never happened (keyed twice, wrong company, cancelled before delivery), the owner VOIDS the invoice instead: Sales → the invoice → Void, in Taokeh. There is deliberately no AI lane for voiding. And if the sale did happen but the invoice was typed wrong — wrong line, wrong quantity or price, wrong date — that is a correction, not a credit: use update_invoice_draft. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesREQUIRED. 'against_invoice' = a return / short delivery / price correction on a SPECIFIC invoice (the usual case — give originalDocId or originalDocNumber). 'allowance' = a standalone money credit with NO source invoice (give the customer instead). They are different documents; when it isn't clear, ask the user which invoice it is against.
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, in the reviewer's language, naming what the human should double-check before approving — whether the goods actually came back, an ambiguous quantity, which invoice you matched it to. Not lengthy reasoning.
cnDateYes
reasonNoWhy the credit is given — 'damaged goods returned', 'short delivery', 'agreed price adjustment'. It prints on the credit note.
customerNoallowance ONLY: the customer name, resolved with resolve_customer first. A credit note reduces an EXISTING customer's balance and can never create a customer. For an against_invoice credit note the customer comes from the invoice — leave this out.
referenceNoThe credit-note number already printed on paper, if any. Leave it out and Taokeh numbers it (CN…).
customerIdNoallowance: the resolved customer id instead of the name.
needsReviewNo
printedTotalNoThe total printed on the paper, if any. Cross-check only — the server computes the real total and flags a mismatch on the approval screen.
goodsReturnedNoAn ADVISORY hint only: it pre-ticks the reviewer's 'the goods came back into stock' checkbox. It does NOT decide the stock movement — the human does, at approval. Ignored for an allowance (always money-only).
originalDocIdNoagainst_invoice: the ORIGINAL invoice's id, from search_documents. The server verifies it exists, is an INVOICE and whose it is — it never guesses.
originalDocNumberNoagainst_invoice: the printed invoice number, when you have no id. Refused if more than one document carries it — find the right one with search_documents.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the all-false annotations, the description discloses crucial behavioral traits: the tool does NOT post to the books, it creates a pending draft that a human reviews/approves; only after approval does it reduce balance, reverse revenue/SST, and restock. It reveals that Taokeh stores amounts negative internally so the caller must send positives, that over-quantity lines are refused with a message naming the remaining available quantity, that goodsReturned only pre-ticks a checkbox and never decides stock movement, and that needsReview should be set with a short note. No annotation contradiction exists — readOnlyHint=false is consistent with a draft-creating write operation.

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 almost every sentence carries operational safety value for a financially high-stakes document type. It is front-loaded with the core purpose and the critical 'does NOT post to the books' caveat. It loses one point for being somewhat stream-of-consciousness — the allowance-vs-invoice rules, voiding guidance, and correction guidance could be grouped more tightly — yet the density of irreplaceable information justifies 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?

For a 13-parameter financial tool with no output schema and all-false annotations, the description is exceptionally complete: it covers both kind variants and their constraints, the approval/side-effect model, amount sign conventions, quantity limits, the goodsReturned advisory semantics, reviewer-note expectations, and the full decision tree for when a credit note is the wrong document. The only minor gap is that it never states what the tool returns on success (draft id?), but given the emphasis on downstream human approval and revision paths, this does not materially impair an agent's ability to invoke and follow up correctly.

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?

At 77% schema coverage, the description still adds substantial meaning beyond the schema: kind is given a decision rule ('when it isn't clear, ask the user which invoice it is against'), originalDocId is tied to a resolution workflow (search_documents), quantity is constrained by what the invoice actually sold net of prior credit notes with an example warning against unit conversion, and goodsReturned/notes semantics are sharpened beyond their schema text. The description compensates for the uncovered parameters and enriches the covered ones.

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 (File), a specific resource (a CREDIT NOTE draft into Taokeh), and the document's financial meaning (sales return, short delivery, price correction, or allowance that reduces what a customer owes). It also distinguishes the tool from its siblings by explaining what it is NOT: not a voided invoice, not an invoice correction (update_invoice_draft), not a re-filing (revise_draft). An agent can tell exactly what this tool does 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 Guidelines5/5

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

The description gives explicit when-to-use guidance: a credit note is right only when something changed AFTER the sale. It names the alternatives with conditions — owner voids the invoice if the sale never happened, update_invoice_draft if the invoice was typed wrong, revise_draft if the draft was filed wrong — and even notes there is 'deliberately no AI lane for voiding'. It also instructs to shape fields with intake_contract and resolve the original invoice with search_documents first, making the invocation workflow explicit.

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

create_debit_note_draftFile debit-note draftAInspect

File a SELL-SIDE DEBIT NOTE draft into Taokeh — an ADDITIONAL CHARGE on an invoice this business already issued (an undercharge, a price revised upward after delivery, a surcharge that was missed). This does NOT post to the books: it creates a pending draft the user reviews and approves in Taokeh, and only then does it increase what the customer owes and the output SST. Shape the fields with intake_contract(doc_type:'sales_debit_note') first. THE ORIGINAL INVOICE IS REQUIRED: find it with search_documents and pass its id as originalDocId. There is no allowance or standalone shape here — unlike a credit note, a debit note with no invoice behind it is not a document; if there is nothing to correct upward, the right document is a NEW INVOICE (create_invoice_draft), so say that rather than filing this. CHARGE THE SHORTFALL, NOT THE NEW PRICE: unitAmount is the amount being ADDED per unit, and quantity defaults to 1 because an additional charge is usually one line of money. Every line must name a product that actually appears on that invoice; anything else is refused. MONEY ONLY, ALWAYS — a debit note moves no stock, touches no COGS, and has no restock option anywhere in Taokeh (there is no goodsReturned field on this tool and no checkbox on its review screen), so a one-tap approval is money-only by construction and not by fence. If EXTRA GOODS were delivered, raise a new invoice instead. There is NO cap on the charge, so the approver is shown the original invoice's own total beside yours — keep the figure defensible. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check) for any doubt. Filed it wrong? Use revise_draft (kind: 'sales_debit_note') rather than filing a second one. This is the SELL side; Taokeh's /debit-notes page is the separate BUY side (a purchase return against a supplier bill), which has no AI draft lane. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, in the reviewer's language, naming what the human should double-check before approving — which invoice you matched it to, where the figure came from. Not lengthy reasoning.
dnDateYes
reasonNoWhy more is charged — 'price revised upward after delivery', 'surcharge missed'. It prints on the note.
customerNoOPTIONAL CROSS-CHECK: the customer you believe the invoice belongs to. The customer comes FROM the invoice; sending a name that does not match is refused, which is exactly what it is for.
referenceNoThe debit-note number already printed on paper, if any. Leave it out and Taokeh numbers it (DN…).
customerIdNoThe resolved customer id, as the same cross-check.
needsReviewNo
printedTotalNoThe total printed on the paper, if any. Cross-check only — the server computes the real total and flags a mismatch on the approval screen.
originalDocIdNoREQUIRED (this or originalDocNumber): the ORIGINAL invoice's id, from search_documents. The server verifies it exists, is an INVOICE and whose it is — it never guesses, and it will not file a debit note without one.
originalDocNumberNoThe printed invoice number, when you have no id. Refused if more than one document carries it — find the right one with search_documents.

TDQS

A4.7/5.0
Behavior5/5

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

Given the annotations are all false/neutral, the description carries the full burden. It discloses key behaviors: creates a pending draft, not posted to books; requires an original invoice; money-only with no stock/COGS effects; no cap on charge; server validation; and why the review screen shows the original total.

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 highly structured and information-dense. Each sentence serves a purpose, clarifying complex domain rules. Slightly verbose, but appropriate for the complexity of the financial document.

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

Completeness4/5

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

The description covers the tool's purpose, prerequisites, limitations, review workflow, and parameter nuances comprehensively. However, it does not describe the return value/output, which would be helpful since there is no output schema. Otherwise, it is nearly 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 high (73%), but the description adds crucial semantics beyond the schema, such as unitAmount being the 'additional' amount not the new price, quantity defaulting to 1, and originalDocId requirements. This enhances the parameter understanding beyond the schema alone.

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

Purpose5/5

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

The description clearly states the tool's purpose: filing a SELL-SIDE DEBIT NOTE draft, an additional charge on an existing invoice. It explicitly contrasts this with credit notes, new invoices, and buy-side debit notes, making it easily distinguishable from siblings.

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

Usage Guidelines5/5

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

It provides explicit when-to-use and when-not-to-use guidance, including alternatives like create_invoice_draft for extra goods or new invoices, revise_draft for corrections, and clarifies the sell-side vs buy-side distinction. This is exemplary.

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

create_expense_draftFile expense draftAInspect

File a paid-expense DRAFT into Taokeh from a receipt you've read. This does NOT post to the books — it creates a pending draft the user reviews and approves in Taokeh; only then does it hit the ledger. Shape the fields with intake_contract + expense_accounts first. Set amountUncertain when any digit of the printed total is uncertain; set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what the human should double-check — not lengthy reasoning) for any other doubt. If you have the ORIGINAL receipt image/PDF, attach it — it rides the draft and lands on the posted entry automatically on approval, so the user never has to re-upload it. Small files: pass attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYes
memoNo
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a vendor/customer you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
amountYes
currencyNo
inputTaxNo
referenceNo
needsReviewNo
shoeboxItemIdNoThe id of a SHOEBOX photo (from shoebox_items) that this draft was read from — the paper someone in the business snapped and sent in. Taokeh attaches ITS OWN stored copy of that photo to the draft, so DO NOT also send the image: no re-upload, no base64, nothing to truncate. Mutually exclusive with attachmentBase64 and attachmentToken. The item must still be waiting: one already booked, set aside, or already carrying a pending draft is refused with the reason. Approving the draft closes that shoebox item against the document it became.
amountUncertainNo
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the posted entry on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL receipt as base64 — SMALL files only (a few KB). Base64 inside a tool call is costly, so for a real receipt photo or a multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the posted entry on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
debitAccountCodeYes
creditAccountCodeYes
attachmentFilenameNoOptional original filename for the attachment, e.g. receipt.jpg.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only say this is a non-read, non-idempotent write; the description enriches that with the exact side-effect shape: it creates a pending review draft that does not hit the ledger until user approval, and the attachment rides through to the posted entry. It also discloses rejection semantics (truncated base64 and bad/oversize files are rejected, nothing filed) and the shoebox-item lifecycle (approval closes the item). No contradiction with annotations.

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

Conciseness5/5

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

The description is long but every sentence carries a decision-relevant instruction — no filler. It is front-loaded with the core purpose and flows logically from draft lifecycle to field shaping to the attachment decision tree.

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 tool with no output schema and minimal annotations, this is remarkably complete: it covers prerequisites, the staged approval lifecycle, failure modes, shoebox-item interaction, and all attachment alternatives. The only thing unspecified is the response shape, which is a minor gap given the depth elsewhere.

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 only 44%, so the description must compensate, and it does: it defines when amountUncertain should be true, how to write a SHORT reviewer note, and the three-way attachment routing with mutual-exclusion rules. It deliberately delegates account-code semantics to intake_contract, which is a reasonable design choice rather than a gap.

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 and resource ('File a paid-expense DRAFT into Taokeh from a receipt you've read'), which immediately scopes it away from the many sibling draft creators (create_bill_draft, create_invoice_draft, create_receipt_draft). The draft-vs-posted distinction further pins down what the tool uniquely does.

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

Usage Guidelines5/5

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

The description gives explicit prerequisites ('Shape the fields with intake_contract + expense_accounts first'), precise trigger conditions for amountUncertain and needsReview, and a full decision tree for attachments — small files inline, big files via request_attachment_upload, and a sandbox fallback. It even states the negative rule ('never both'), so the agent knows what to avoid.

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

create_invoice_draftFile invoice draftAInspect

File a sales-invoice DRAFT into Taokeh from a sales note you've read. This does NOT post to the books — it creates a pending draft the user reviews and approves in Taokeh; only then does it post (and move stock). Shape the fields with intake_contract(doc_type:'invoice') + resolve_customer + resolve_product first. The server re-computes every line quantity from the tally and the grand total (with SST) — so present your working, but the server's figures are authoritative. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. If you have the ORIGINAL sales note image/PDF, attach the original document you extracted from — the owner sees it beside the draft at review (s.82 record-keeping) and it lands on the posted invoice automatically on approval, so the user never has to re-upload it. Small files: attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
termNoThe payment term exactly as the paper states it ('Due on Receipt', 'Net 7', 'Net 14', 'Net 30', 'Net 60'). Anything else the note actually says is kept verbatim and shown to the reviewer as-is — do not round it to the nearest familiar term. Leave it out when the paper states none.
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a vendor/customer you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
refNoNoThe CUSTOMER's own document number as printed on the note — their delivery-order number or purchase-order number ("DO 1074", "PO 88231"). NOT the invoice number: that is `reference`. Leave it out when the paper shows none; never copy the invoice number into it.
dueDateNoThe due date when the paper states one outright. For one of the five preset terms you can leave it out — Taokeh fills the due date on the draft (invoice date + 0/7/14/30/60 days) and the owner sees it on the approval screen. Send it to override that, or when the paper's due date does not follow the term. A term Taokeh does not recognise derives NOTHING, so state the due date yourself on those or the invoice posts due on its own issue date.
customerNo
saleDateYes
referenceNo
customerIdNo
needsReviewNo
printedTotalNo
paymentMethodYes
shoeboxItemIdNoThe id of a SHOEBOX photo (from shoebox_items) that this draft was read from — the paper someone in the business snapped and sent in. Taokeh attaches ITS OWN stored copy of that photo to the draft, so DO NOT also send the image: no re-upload, no base64, nothing to truncate. Mutually exclusive with attachmentBase64 and attachmentToken. The item must still be waiting: one already booked, set aside, or already carrying a pending draft is refused with the reason. Approving the draft closes that shoebox item against the document it became.
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the posted invoice on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL sales note as base64 — SMALL files only (a few KB). For a real photo or multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the posted invoice on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoOptional original filename for the attachment, e.g. sales-note.jpg.
confirmNewCustomerNoSet to true ONLY after the user has EXPLICITLY confirmed this customer is genuinely new. It skips the near-miss guard (which rejects a name that looks like shorthand for an existing customer). Never set it to push a near-miss through — ask the user first.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations carry only readOnly=false / idempotent=false, so the burden falls on the description, and it exceeds it: the server re-computes line quantities and the grand total (with SST) and its figures are authoritative; a quantity sent alongside a parseable tally is advisory and shown beside the server's; truncation protection (attachmentBytes rejects a truncated base64); already-booked shoebox items are refused with a reason; confirmNewCustomer skips the near-miss guard; and approval closes the shoebox item and lands the attachment on the posted invoice. No statement contradicts 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?

The description is long by absolute measure, but each block conveys non-obvious operational truth (failed-upload semantics, reviewer-note length guidance, sandbox fallback, s.82 record-keeping rationale) that an agent cannot infer from the schema. It is front-loaded with the core purpose and no-posting caveat. It is not a single crisp paragraph, so it sacrifices some readability, but the density is earned for a 20-param, compliance-sensitive mutation.

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 and 20 params, the description covers the success model (pending draft the user reviews and approves, only then posting and moving stock), failure modes (truncated base64 rejected, oversized/bad-type file rejected and nothing filed, shoebox item refused if already booked/set aside), and the complete attachment decision matrix including the allowlist sandbox case. The gaps are modest: the return shape of a successful call is not described, and a few params (printedTotal, working, customer/customerId) remain unexplained.

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 60%, so the description must compensate, and it does for the highest-stakes params: quantity (omit on measurement-profile, advisory vs authoritative), term (verbatim, don't round to familiar terms), dueDate (derivation from preset terms, no deriivation for unknown terms), attachment fields (exclusive, size rules, mutual exclusion), shoeboxItemId semantics, and confirmNewCustomer guard. Gaps remain for working, printedTotal, and customer/customerId, which gain no meaning beyond their bare names in either schema or description.

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 starts with a specific verb-resource pair: 'File a sales-invoice DRAFT into Taokeh from a sales note you've read', which uniquely identifies the tool versus siblings like create_bill_draft or create_redit_note_draft. It immediately adds the bordering caveat ('This does NOT post to the books') that distinguishes the draft-filing action from a final booking. This is about as distinct a purpose statement as the domain allows.

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 explicit workflow preguisites ('Shape the fields with intake_contract(doc_type:'invoice') + resolve_customer + resolve_product first') and explicit conditional routing for the attachment dimension: inline for small files, request_attachment_upload for real photos/PDFs, sandbyox fallback when the shell cannot reach taokeh.my, and shoeboxItemId instead of any upload. What is missing is an explicit 'use create_redit_note_draft when...'-style exclusion naming sibling draft tools, so this earns 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.

create_journal_draftFile adjusting journal draftAInspect

File an ADJUSTING JOURNAL ENTRY as a draft in Taokeh — the accountant's entry, not a document: accruals, prepayments, depreciation, corrections, reclassifications, year-end adjustments, and REVERSING entries. This does NOT post to the books: it creates a pending draft with the debits and the credits laid out for the user to see, and only their approval writes it to the ledger. Shape the fields with intake_contract(doc_type:'journal') first — it returns this company's REAL chart of accounts, which is what every accountRef must match. IT MUST BALANCE TO THE SEN: debits equal credits or the draft is refused, with the difference named. Each line carries exactly one side (debit OR credit), and at least two lines are required. Accounts are matched by CODE (best) or by their exact name; an unknown ref is refused and an ambiguous name reports the candidates rather than picking. THIS TOOL NEVER CREATES AN ACCOUNT — if the adjustment needs one that does not exist, tell the user to add it in Taokeh and file again. FIXING A WRONG ENTRY THAT IS ALREADY POSTED: file a REVERSING entry here. Taokeh's connector never edits and never deletes posted history — that is deliberate and it is the point: a ledger you can rewrite is not a ledger, and every entry must stay auditable. So find the wrong entry with search_journal, file a reversing journal dated today (its debits become credits and its credits become debits, same accounts, same amounts), then file the correct entry. Tell the user plainly that this is what you are doing and why, rather than reporting that you 'cannot' fix it. CONTROL ACCOUNTS ARE ALLOWED BUT NEVER SILENT: a line on accounts receivable, accounts payable, inventory, the SST control or opening-balance equity is reconciled to a subledger, so a journal there moves the control with no document behind it and the aging-vs-control tie-out will show the difference. Such a draft is filed and flagged — it can be approved ONLY on its full review page in Taokeh, never by a one-tap email approval or a deck swipe. Say in notes why the control line is right. WHAT NOT TO USE THIS FOR: anything that has a real document. A supplier bill is create_bill_draft, a sale is create_invoice_draft, a paid expense is create_expense_draft, a customer payment is create_receipt_draft. Those carry party, SST and stock consequences a raw journal silently skips. Attach the WORKING PAPER you read the adjustment off — the depreciation schedule, the accrual computation, the bank letter. It rides the draft and the approver sees it beside your figures. Prefer request_attachment_upload → attachmentToken; if your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist) send attachmentBase64 + attachmentMediaType inline instead — correct even for a full PDF — always with attachmentBytes, the file’s decoded size on disk, so a truncated paste is rejected instead of filed. Never both. Set needsReview and add a SHORT reviewer note in notes for any doubt. Filed it wrong? Use revise_draft (kind: 'journal') rather than filing a second one.

ParametersJSON Schema
NameRequiredDescriptionDefault
memoNoWhat the entry is FOR, in one line — "accrue December electricity", "reverse the duplicated August rent". It prints on the entry and is the first thing the approver reads.
linesYesAt least two lines. The debits must equal the credits TO THE SEN — an unbalanced entry is refused with the difference named. ⛔ LINE KEYS ARE STRICT: a key this schema does not list is REFUSED BY NAME and NOTHING is filed.
notesNoA SHORT reviewer note: one or two plain sentences, in the reviewer's language, naming what the human should double-check before approving — which schedule the figure came from, which entry this reverses, why a control-account line is right. Not lengthy reasoning.
entryDateYes
referenceNoYour own reference for the adjustment, if there is one (a schedule number, a working-paper ref).
clientTotalNoYour own arithmetic for the entry total — carried onto the review screen for the human to compare against, never used to compute anything.
needsReviewNo
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Mutually exclusive with attachmentBase64.
attachmentBase64NoThe supporting WORKING PAPER as base64 — SMALL files only. For a real schedule or a multi-page PDF use request_attachment_upload instead (attachmentToken). A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoThe original filename, for the reviewer.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only supply shallow signals (readOnlyHint=false, destructiveHint=false, etc.), and the description adds rich behavioral truth far beyond them: the draft does NOT post to the books, an unbalanced entry is refused with the difference named, an unknown account ref is refused, and 'THIS TOOL NEVER CREATES AN ACCOUNT'. It also discloses the deliberate never-edit/never-delete posted history policy and the approval restriction for flagged control accounts - exactly the behavioral context an agent needs and 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?

The description is long, but it is structured into clearly distinct concerns - non-posting behavior, balance rule, account matching, reversing workflow, control accounts, exclusions, attachments - with the core purpose front-loaded in the first sentence. Every paragraph addresses a failure mode or policy constraint an agent would otherwise encounter; only the ledger-integrity philosophy explanation runs slightly long.

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

Completeness5/5

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

For a 13-parameter accounting tool with no output schema, the description covers the full decision surface: what it files, what it refuses, how approval works, integration with intake_contract/search_journal/revise_draft/request_attachment_upload, and edge cases (truncated attachments, ambiguous account names, unreachable host). 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 85%, so the baseline is 3 and the schema already documents each parameter thoroughly. The description adds decision heuristics beyond the schema: the attachmentToken-vs-attachmentBase64 choice ('Prefer request_attachment_upload... if your shell cannot reach taokeh.my'), the rule that attachmentBytes must always accompany base64 to reject truncated pastes, and guidance on what `notes` should contain for control lines and doubts.

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: 'File an ADJUSTING JOURNAL ENTRY as a draft', and immediately carves out the core differentiator: 'the accountant's entry, not a document'. It also enumerates the exact use cases (accruals, prepayments, depreciation, corrections, reclassifications, year-end, reversing entries), leaving no ambiguity about what this tool is for.

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 'WHAT NOT TO USE THIS FOR' section that names the exact sibling to pick instead: create_bill_draft, create_invoice_draft, create_expense_draft, create_receipt_draft. It also chains the workflow instruction - use intake_contract for the chart of accounts, search_journal to locate a posted error, revise_draft to fix a wrongly filed draft - so the agent knows exactly when this tool is and is not the right call.

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

create_payment_draftFile a pending supplier-payment draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. File a SUPPLIER-PAYMENT draft ("we paid Ah Seng RM5,000 from Maybank on Tuesday against bills 12 and 14"). This does NOT post: only the owner's approval writes a real bank payment and settles the bills, and when it does, accounts payable and the bank move exactly as they would if the owner had matched the line in Banking. A payment settles an EXISTING supplier's open bills: resolve the supplier (resolve_vendor) and see what is owed (ap_aging, search_documents) first, then give EITHER a lump total (auto-allocated oldest-first) OR explicit per-bill allocations. PREFER purchaseId over reference in an allocation: a supplier's own bill number is NOT unique in Taokeh, so a reference that matches two open bills is refused naming both rather than guessed. MYR only — a foreign-currency bill is refused and routes to Banking → Match, which handles the exchange difference. Amounts are RINGGIT, the same figures ap_aging and search_documents show you — never sen, never a foreign figure converted by you. A CREDIT CARD can't be the paying account here: paying a supplier on a card is a spend that arrives on the card's own statement — import that statement instead. IF THIS COMPANY IMPORTS BANK STATEMENTS and the payment is already sitting on an imported line, do NOT file here — propose the allocation on that line with draft_bank_classification. Filing it here would put the same money in Taokeh twice, and the server refuses when it can see the imported line. The server re-derives the allocation against live outstanding at create AND at approval, so its figures are authoritative and a bill settled in the meantime makes the draft refuse rather than over-pay. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. Filed it wrong? Use revise_draft (kind: 'payment') rather than filing a second one. If you have the payment proof (transfer slip, remittance advice), attach the original document you extracted from — the owner sees it beside the draft at review (s.82 record-keeping) and it lands on the settlement entry automatically on approval. Small files: attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a supplier you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
totalNoA lump ringgit amount to auto-allocate oldest-first across the supplier’s open bills. Give this OR explicit allocations — never both.
vendorNoThe supplier name, resolved with resolve_vendor first. A payment settles an EXISTING supplier's bills and can never create a supplier.
vendorIdNoThe resolved vendor id, instead of the name.
allocationsNoThe explicit per-bill split, at most 50 lines. Each amount is capped at that bill’s live outstanding by the server.
needsReviewNo
paymentDateYes
printedTotalNoThe total printed on the payment advice, if any. Cross-check only — the server computes the real total and flags a mismatch on the approval screen.
bankAccountIdNoThe PAYING bank/cash account (from intake_contract(doc_type:'payment') → payingAccounts). Optional — omit it and the reviewer picks at approval. A credit-card account is refused by name.
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the settlement entry on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL payment proof (transfer slip / remittance advice) as base64 — SMALL files only (a few KB). For a real photo or multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the settlement entry on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoOptional original filename for the attachment, e.g. transfer-slip.jpg.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.9/5.0
Behavior5/5

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

The description goes far beyond the annotations by explaining that the draft does NOT post until the owner approves, that the server re-derives allocations at create and approval time, that duplicate imported-line filings are refused, and that truncated attachments are rejected. These are critical behavioral details that the sparse annotations do not convey, and there is no contradiction with 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?

The description is front-loaded with the most important safety constraint and nearly every sentence carries functional value. However, it is a dense wall of text with heavy all-caps and long parenthetical asides, which makes parsing harder than necessary; it could be tightened or structured without losing 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 15-parameter mutation tool with no output schema, the description is remarkably complete. It covers prerequisites, allocation rules, currency constraints, credit-card exclusions, the imported-statement duplicate risk, attachment mechanics, review notes, error handling, and what happens at approval. Nothing essential for selecting or invoking the tool 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?

Although schema coverage is already high at 87%, the description adds substantial meaning to parameters: purchaseId should be preferred over reference because supplier bill numbers are not unique, total and allocations are mutually exclusive, attachmentBytes detects truncated base64, and notes should carry only a short reviewer flag. This materially improves correct invocation beyond the raw 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 opens with a specific verb and resource: 'FILES A PENDING DRAFT ONLY' and 'File a SUPPLIER-PAYMENT draft'. It clearly distinguishes this tool from the many create_* siblings and from draft_bank_classification by stating exactly what kind of draft it files and that human approval is required before anything posts.

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?

Usage guidance is explicit and thorough. It names concrete alternatives and their trigger conditions: use draft_bank_classification if the payment is already on an imported bank line, use revise_draft if filed wrong, and route foreign-currency or credit-card cases elsewhere. It also prescribes prerequisites like resolve_vendor, ap_aging, and search_documents before filing.

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

create_purchase_order_draftFile purchase-order draftAInspect

File a PURCHASE-ORDER draft into Taokeh — an order you intend to PLACE with a supplier, typically read off their quotation. It POSTS NOTHING and MOVES NOTHING: a purchase order is an intent to buy, so approving it creates no journal entry, no stock movement and no amount owing. The books move later, when the goods arrive and the user converts the order into a bill on its page in Taokeh — a step this tool never takes for them. Approval also saves the order as a DRAFT; issuing it to the supplier is the user's own tap, and Taokeh emails nobody. INVENTORY-ONLY — every line must be a product the company stocks; a service or one-off non-stock charge belongs on the manual purchase-order form. NO SST on this document: a purchase order in Taokeh carries no tax code and no tax line, and input SST is settled on the bill against the supplier's tax invoice. Shape the fields with intake_contract(doc_type:'purchase_order') + resolve_vendor + resolve_product first. The server re-computes every line quantity from the tally and the order total — so present your working, but the server's figures are authoritative. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. Filed it wrong? Use revise_draft (kind: 'purchase_order') rather than filing a second one. Goods that have ALREADY arrived are not this door — use create_bill_draft. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
termNoThe payment/delivery term line, e.g. 'Net 30'.
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before they order — a quantity you weren't sure of, a supplier name you guessed at, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. Leave it empty when there is nothing to flag.
poDateYes
vendorNo
vendorIdNo
referenceNoThe BUYER'S OWN purchase-order number, if they already have one — it becomes this order's document number. NOT the supplier's quotation number (put that in `notes`). Usually omit it: Taokeh numbers the order itself (POxxxx).
needsReviewNo
expectedDateNoWhen the goods are expected, YYYY-MM-DD. Optional — omit it rather than guess.
printedTotalNo
confirmNewVendorNoSet to true ONLY after the user has EXPLICITLY confirmed this supplier is genuinely new. It skips the near-miss guard (which rejects a name that looks like shorthand for an existing vendor). Never set it to push a near-miss through — ask the user first.

TDQS

A5/5.0
Behavior5/5

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

The description goes far beyond the annotations by disclosing concrete side effects and non-effects: no journal entry, no stock movement, no amount owing, no email to the supplier, approval only saves a draft, and the server recomputes quantities authoritatively. It also claries that no SST or tax line exists on the purchase order.

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

Conciseness5/5

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

Dense but well-structured: it opens with the core definition, then states non-effects, exclusions, preparation steps, server authority, and error-recovery routing. Every sentence carries a distinct constraint or decision rule without 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?

Given 11 parameters, no output schema, and a large sibling set, the description covers what to send, how to prepare the data, what the user must still do, what the server will override, and which alternative tool to use fpr different situations. An agent has enough to call and interpret the tool correctly.

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?

With schema coverage at only 45%, the description compensates substantially. It explains the reference field as the buyer's own PO number rather than the supplier quotation, dictates the length and purpose of notes, explains needsReview, describes how quantity is either derived from tally or treated as advisory, and tells the agent to omit expectedDate rather than guess.

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 action: 'File a PURCHASE-ORDER draft into Taokeh', and immediately explains what that means — an intent to place with a supplier. It distinguishes this from a bill by explicitly saying it posts nothing and moves nothing, and from create_bill_draft by noting arrived goods belong to that tool.

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

Usage Guidelines5/5

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

Gives explicit routing rules: use revise_draft if filed wrong, use create_bill_draft if goods have already arrived, and use the manual purchase-order form for non-stock items. It also directs the agent to prepare fields with intake_contract, resolve_vendor, and resolve_product first.

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

create_quote_draftFile quote draftAInspect

File a quotation DRAFT into Taokeh from a request you've read or been told. A quote is an ESTIMATE — it does NOT post to the books or move stock; it creates a pending draft the user reviews and approves in Taokeh, which posts a real quotation they can then convert to an invoice or delivery order. Shape the fields with resolve_customer + resolve_product first. The server re-computes every line quantity from the tally and the grand total (with SST) — so present your working, but the server's figures are authoritative. A quote may have no customer (a walk-in estimate). Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. If you read the request off a document, attach the original document you extracted from — the owner sees it beside the draft at review (s.82 record-keeping) and it lands on the posted quote automatically on approval. Small files: attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both. ⛔ LINE KEYS ARE STRICT (2026-09-09): a key this schema does not list is REFUSED BY NAME — with the key it probably meant — and NOTHING is filed. Unknown keys used to be dropped in silence, which let a line through with its price or its tax code missing.

ParametersJSON Schema
NameRequiredDescriptionDefault
termNoPayment term carried onto the quote, e.g. 'Net 30'. Defaults to 'Due on Receipt'.
linesYes
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a vendor/customer you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
customerNo
quoteDateYes
referenceNo
customerIdNo
validUntilNoOptional "valid until" date for the quotation (YYYY-MM-DD).
needsReviewNo
printedTotalNo
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the posted quote on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL request/quote document as base64 — SMALL files only (a few KB). For a real photo or multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the posted quote on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoOptional original filename for the attachment, e.g. rfq.pdf.
confirmNewCustomerNoSet to true ONLY after the user has EXPLICITLY confirmed this customer is genuinely new. It skips the near-miss guard (which rejects a name that looks like shorthand for an existing customer). Never set it to push a near-miss through — ask the user first.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A5/5.0
Behavior5/5

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

Annotations are minimal (all hints false), so the description carries the behavioral burden and does so thoroughly. It discloses mutation semantics (creates a pending draft, does not post to books), server-side recomputation of quantities and totals, authoritative server figures, rejection of truncated base64, and the near-miss guard behavior for confirmNewCustomer. No contradiction with annotations exists.

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

Conciseness5/5

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

Although the description is long, it is densely informative and front-loaded with the core purpose. Every major clause covers a distinct operational concern: workflow, authoritative computation, reviewer notes, attachment size paths, and sandbox fallback. The structure flows naturally from definition to process to edge cases, and there is no 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?

For a 17-parameter mutation tool with no output schema and minimal annotations, the description is exceptionally complete. It covers the full lifecycle, customerless quotes, measurement-profile quantity derivation, reviewer note style, attachment upload alternatives, and failure modes. An agent has enough context to call the tool correctly and to route around exceptional cases.

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?

With 59% schema coverage, the description substantially compensates for the uncovered parameters. It explains the practical meaning of quantity vs tally/thickness/width, the role of needsReview and notes, the attachment token/base64/bytes relationship, and the confirmNewCustomer guard. This goes well beyond the schema by explaining why and how parameters interact.

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 and resource: 'File a quotation DRAFT into Taokeh'. It clearly distinguishes a quote draft from a posted quotation, invoice, or delivery order by stating it is an estimate and does not post to the books or move stock. This effectively differentiates it from sibling draft tools like create_invoice_draft.

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

Usage Guidelines5/5

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

The description gives explicit workflow direction: resolve_customer and resolve_product first, set needsReview for doubt, and keep reviewer notes short. It also provides concrete alternative routing for attachments—inline base64 for small files vs request_attachment_upload for large ones—and states when to inline despite the sandbox restriction. This is strong when-to-use guidance tied to real conditions.

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

create_receipt_draftFile receipt draftAInspect

File a customer-payment DRAFT into Taokeh ("customer paid X"). This does NOT post — it creates a pending draft the user reviews and approves in Taokeh; only then does it write a real bank receipt and settle the invoices. A receipt settles an EXISTING customer's open invoices: resolve the customer (resolve_customer) and see what they owe (open_invoices) first, then give EITHER a lump total (auto-allocated oldest-first) OR explicit per-invoice allocations. MYR only — a foreign-currency invoice is refused and routes to Banking → Payments. The server re-derives the allocation against live outstanding, so its figures are authoritative. Set needsReview and add a SHORT reviewer note in notes (one or two sentences naming what to double-check — not lengthy reasoning) for any doubt. If you have the payment proof (bank-in slip / remittance advice), attach the original document you extracted from — the owner sees it beside the draft at review (s.82 record-keeping) and it lands on the settlement entry automatically on approval. Small files: attachmentBase64 + attachmentMediaType inline. Send attachmentBytes (the original file’s decoded size) with it so a truncated base64 is rejected instead of filed. Anything bigger: request_attachment_upload → PUT the bytes → pass the returned attachmentToken — unless your shell cannot reach taokeh.my (a sandboxed client behind a network allowlist), in which case inline it anyway, with attachmentBytes; never both.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note: one or two plain sentences, written in the reviewer's language, flagging what the human should double-check before approving — a smudged or ambiguous total, a vendor/customer you weren't sure of, a judgment call you made. The reviewer reads this on a small approval card, so keep it brief and human. This is NOT a place to dump lengthy reasoning, your working, or boilerplate — just the one thing to check. Leave it empty when there is nothing to flag.
totalNo
customerNo
customerIdNo
allocationsNo
needsReviewNo
receiptDateYes
printedTotalNo
bankAccountIdNo
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the file bytes to its uploadUrl. Use this instead of attachmentBase64 for any real photo/PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The uploaded file rides the draft and lands on the settlement entry on approval, exactly as an inline one does.
attachmentBase64NoThe ORIGINAL payment proof (bank-in slip / remittance advice) as base64 — SMALL files only (a few KB). For a real photo or multi-page PDF use request_attachment_upload instead (attachmentToken). Rides the draft and lands on the settlement entry on approval — no re-upload. A bad type/oversize file is rejected and NOTHING is filed.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoOptional original filename for the attachment, e.g. bank-in-slip.jpg.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'image/jpeg' or 'application/pdf'. Required when attachmentBase64 is given.

TDQS

A4.9/5.0
Behavior5/5

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

While annotations only hint at write behavior (readOnlyHint=false), the description discloses critical behavioral traits: it does not post immediately, the server re-derives allocation against live outstanding, attachmentBytes prevents truncated-file acceptance, and attachmentToken vs attachmentBase64 are mutually exclusive. It also states that store of proof rides the draft to settlement. These go well beyond annotation coverage and set accurate expectations.

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 intentionally so—given the complexity of 15 parameters and multi-step attachment logic. It is front-loaded with the core purpose and workflow, then methodically covers allocation and attachment rules. Each sentence adds substantive guidance; no filler. The length is justified given the tool's intricacy.

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 tool with 15 parameters, no output schema, and complex behaviors (allocation, attachment transport, reviewer notes), the description is thorough. It covers prerequisites (customer resolution, open_invoices), decision points (total vs allocations), exception handling (foreign currency, network limits), and security details (attachmentBytes for truncation). An agent has everything needed to invoke it correctly.

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 only 47%, so the description must compensate—and it does extensively. It explains the semantics and interplay of total vs allocations, needsReview, notes, and all attachment-related parameters (base64, token, bytes, sha256, mediaType, filename). It clarifies when each attachment method is appropriate and the role of attachmentBytes in detecting truncation. This far exceeds what the schema provides.

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

Purpose5/5

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

The description states a specific verb ('File') and resource ('customer-payment DRAFT'), and clarifies it does NOT post but creates a pending draft for user review. It explicitly outlines the workflow (resolve customer, see open invoices, then submit total or allocations). This clearly distinguishes it from sibling draft tools (e.g., create_invoice_draft, create_bill_draft) by emphasizing the receipt-settlement purpose.

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

Usage Guidelines5/5

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

The description provides explicit when-to-use instructions: resolve the customer first, check open invoices, then choose either a lump total or per-invoice allocations. It also names alternatives (request_attachment_upload for large files) and gives routing guidance for foreign-currency invoices (refused, route to Banking → Payments). It even specifies conditions for when to inline vs. out-of-band attachment, including network limitations.

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

create_recurring_invoice_draftFile a pending recurring-invoice draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING IS CREATED UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose a NEW recurring invoice — a billing schedule that issues the same invoice to the same customer every month, quarter or year (a retainer, a subscription, a maintenance contract, rent). This does NOT create anything: it files a pending DRAFT the owner reviews and approves; only that tap saves the schedule. Give the customer (customerId from resolve_customer, or customer as an EXACT existing customer name — this tool never creates a customer), the lines (each a real catalogue product by productId or exact sku, with the quantity and the agreed unit price that will be billed EVERY cycle), the cadence, and the startDate — whose day of the month becomes the billing anchor (a 31st anchor lands on the 28th/29th/30th in shorter months). Optionally endDate, maxOccurrences, title, notes and paymentMethod (CREDIT = the customer owes it and pays later, CASH = settled at issue; these book differently, so ask rather than guess). ⛔ WHAT IT CANNOT DO: it cannot set issueMode: "auto" — a schedule you propose files an invoice DRAFT each cycle for a person to approve, and nothing proposed through this connector may buy itself the right to post invoices unattended; the owner switches that on themselves if they want it. It cannot set MFRS 15 revenue spreading (recognition), which is an accounting-policy decision on the schedule's own page. It cannot set the next issue date directly — that is derived from the start date and the cadence, and the review page tells the owner the exact date the FIRST invoice would be issued before they approve. BE HONEST: never guess a contracted price or a start date — leave the schedule unproposed and ask.

ParametersJSON Schema
NameRequiredDescriptionDefault
linesYesWhat gets billed every cycle. Every line must be a real catalogue product. ⛔ LINE KEYS ARE STRICT: a key this schema does not list is REFUSED BY NAME and NOTHING is filed.
notesNoA SHORT reviewer note, in the reviewer's language: what this schedule bills and what they should double-check.
titleNoA short label for the schedule, e.g. 'Monthly retainer — Acme'. Optional; it never prints on the invoice.
cadenceYes
endDateNoStop issuing after this date. Optional.
customerNoAn EXACT existing customer name. A name that matches nobody is refused — this tool never creates a customer.
startDateYesThe first billing date. Its DAY OF THE MONTH becomes the anchor for every later cycle. A date in the past does not backfill — the first invoice lands on the first cycle on or after today.
customerIdNoThe customer id from resolve_customer. Give this OR `customer`.
needsReviewNoSet true when something gave you pause — a price the user was unsure about, a start date you inferred.
paymentMethodNoCREDIT (default) = the customer owes it. CASH = settled at issue. Ask the user; these book differently.
maxOccurrencesNoStop after this many invoices. Optional.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already mark this as non-readOnly and destructive, so the draft-not-created nuance adds real behavioral context beyond the schema, including that the owner's tap is what saves the schedule. The description also reveals that issueMode auto is blocked and that first-issue date is derived and shown on the review page, which is valuable. It stops short of detailing failure modes or rate limits, but for a draft-creation tool the main consequences are well covered.

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 every section earns its place: it front-loads the draft-only warning, explains the schedule concept, maps the key parameters, lists prohibitions, and closes with an honest-use directive. It is arguably verbose, but the density of operational cautions justifies the length for a high-stakes billing 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?

With no output schema and annotations that don't clarify side effects, the description carries the burden of explaining what happens after invocation—the draft goes to a human review page—and what the agent must not do. Missing an explicit statement of what a successful response contains, but for a draft-filing tool the workflow and constraints are complete enough to invoke 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 91% and the schema already documents most parameters, but the description adds essential semantics: customer must exist exactly, lines must be real catalogue products, startDate day becomes billing anchor with month-end handling, and paymentMethod books differently. It reinforces the meaning of maxOccurrences and endDate indirectly, but relies on the schema for remaining details, hence not 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?

The description opens with a clear, emphatic statement that this tool files a pending draft only and creates nothing until human approval, and it names the resource (recurring invoice draft) with the specific verb 'file'. It further differentiates from siblings like create_invoice_draft and update_recurring_invoice_draft by explaining that this proposes a new billing schedule, so an agent can select it confidently.

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

Usage Guidelines5/5

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

The description gives explicit guidance: use it to propose recurring invoices (with retainer/subscription/rent examples), and it explicitly says what it cannot do (set issueMode auto, set MFRS 15 recognition, set next issue date directly). It also tells the agent to ask rather than guess when paymentMethod or prices/dates are uncertain, effectively defining when not to invoke the tool.

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

daily_briefDaily briefAInspect

Your morning brief in one call: today's and this-month's sales & expenses, cash position (cash.total is LIQUID money only — cash + banks + gateway float; any owner advance comes back separately as cash.ownerFunding, and any credit-card debt as cash.cards / cash.cardsOwing — both are liabilities that must never be added to, or netted against, the cash total), who owes you (top debtors + overdue buckets), what's waiting for your approval (approvals.total counts DECISIONS, not rows: a real approval contributes its item count, while an operational to-do like "listings to link" counts as 1 however long its backlog — read each item's own count for the size. A STAGED SET (staged_documents, staged_products, …) is one decision too, so its count is always 1: read rows for how many are actually waiting, flagged for how many need a human look, and fenced for how many cannot be entered while the accounting start date stands where it is (they are dated on or before it, so the opening balances already carry them). A fenced row is not work the owner can finish on this queue: the remedies are to leave it out, or to move the accounting start date — after which Taokeh re-checks the fence and the row becomes enterable), tax position, and low stock. Assembles the same figures as the individual tools (business_snapshot, cash_position, ar_aging, tax_position, low_stock) plus your pending-approval queue, so "brief me" is a single read.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior1/5

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

The description claims the tool is a read operation ('single read') and a pure aggregation, while the annotations include `readOnlyHint: false`. This is a direct contradiction: the agent cannot rely on the description's implicit read-only promise and the annotation's mutability signal. Rule scores this 1 because the description contradicts the structured annotations.

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

Conciseness4/5

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

The description is long, with extensive parentheticals about cash semantics and approval counting. All the details are load-bearing and the main purpose is front-loaded ('Your morning brief in one call'). The sentence structure is somewhat heavy, but it is far from tautological: it earns its length.

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?

There is no output schema, so the description carries the burden of understanding the response. It does well for the cash fields and approvals (defining `cash.total`, `cash.ownerFunding`, `cash.cards`, and `approvals.total` with careful liability and count semantics). However, some high-level outputs (tax position, low stock, overdue bucket details) are only named, not explained, making it slightly incomplete as an output reference.

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?

There are zero input parameters, so there is no parameter semantics description needed to fill in; the baseline for a parameterless tool is 4. The description correctly spends no space on parameters and focuses instead on what the tool returns.

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

Purpose5/5

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

The description uses a specific, comprehensible framing: 'Your morning brief in one call' and enumerates exactly what the tool surfaces: sales/expenses, cash position, debtors, approvals, tax and low stock. It also names the sibling tools's individual reads it aggregates, which distinguishes it from business_snapshot, cash_position, ar_aging, tax_position, and low_stock.

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

Usage Guidelines4/5

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

The description clearly establishes the intended use case: a one-call morning brief, contrasted with individual tools via 'Assembles the same figures as the individual tools' and 'brief me is a single read.' It does not explicitly provide a 'when not to use' list or direct the agent to a more specific sibling for deeper drill-down, keeping this at a 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.

draft_bank_classificationSuggest bank-row categories (human reviews in Taokeh)AInspect

Propose a category (and optionally a contact) for up to 50 bank rows still waiting for review — imported statement lines AND rows the owner typed in by hand, which land as UNCATEGORIZED — get their ids from bank_review_queue. PROPOSALS ONLY: this writes a suggestion the owner sees as an 'AI suggestion' badge on the Banking → Review screen; it never confirms, never posts, and nothing you send here moves money — the owner reviews and posts every line in /banking. Only SUGGESTED/UNCATEGORIZED rows accept a proposal (already-decided CONFIRMED/POSTED/IGNORED rows are rejected). category must be one of the review screen's own set. contactName applies only to CUSTOMER_PAYMENT (a customer) or SUPPLIER_PAYMENT (a vendor) and must match an EXISTING contact exactly — an unresolvable name rejects that row (create the contact first, or omit it). accountCode proposes the LEDGER ACCOUNT for the row (e.g. a hosting bill to 6500) and is accepted ONLY for the two categories whose account the owner picks by hand — OTHER and INTERNAL_TRANSFER. Every other category already books against a fixed account (a customer payment to receivables, a bank charge to bank charges, and so on), so sending accountCode with one is rejected and the reply names the account that category already carries. The code must exist in this company's chart (expense_accounts lists the expense side); a bank or credit-card account's own ledger account is refused, because that would post the money against itself. CARD_PAYMENT is the one category that REQUIRES accountCode, and takes only a credit-card account: it means "this bill settles that card", so propose it with the card's code or not at all — a card payment is never an expense, and naming an expense account (or naming a card account under OTHER) is refused, because the card's spending was already booked line by line from the card statement. The account you propose arrives PRE-SELECTED in the owner's account dropdown on Banking → Review, marked as proposed by you — it saves them hunting the chart, it does not decide anything: if they have already picked an account themselves, theirs stands. allocations proposes WHICH invoices or bills the money settles — the question Taokeh's own matcher hands to a human whenever the payment is partial, spans several documents, or could clear more than one combination, and the one you may already know from a remittance advice or the payer's own message. Send it ONLY with CUSTOMER_PAYMENT on a money-IN row or SUPPLIER_PAYMENT on a money-OUT row, and ONLY together with contactName, because every line is checked against THAT contact's live open documents: up to 20 entries of { docNumber, amount }, where docNumber is the document number as Taokeh shows it (open_invoices / ap_aging list them). EVERY amount is in RINGGIT, and specifically the outstanding balance as Taokeh reports it on those tools — never the document's own foreign-currency figure, and never its gross total where the two differ; a foreign-currency invoice is settled in Banking, not here. The amounts must add up to the WHOLE line within 0.10 — a proposal that leaves part of the deposit unexplained is refused with the exact shortfall, never trimmed to fit — no line may exceed what its document still owes, and an unknown number, a duplicate, or a document dated AFTER the payment is refused too; the refusal names that contact's own open documents with their outstanding amounts, so you can correct it in one more turn. What it does is PRE-FILL: the owner's Match pane opens with those documents ticked and those amounts entered, under a banner saying you proposed it and quoting your note. It settles nothing — the owner reads it and clicks Save — and if a document has been paid or part-paid since you proposed it, the pane says your proposal no longer fits and fills in nothing rather than allocating a stale figure. It never reaches the one-tap Accept on the payments list either; that button only ever applies Taokeh's own exact match. note is your stated reason (≤300 chars), shown to the owner — write it well, because the owner reads it when deciding. Your proposals are also collected into a 'Proposals from your AI' panel on Banking → Review, where the owner can accept a whole batch of them in one tap after reading them grouped by category with your reasons; that acceptance sets the category and contact only and is still the owner's decision — it never posts to the ledger. If a row's existing suggestion says "You set this rule on ", the OWNER has written a standing rule for that payer (What Taokeh has learned → Bank rules) — proposing something different is allowed and is sometimes right, but say in your note that you are contradicting their own rule, and expect them to keep the rule. Per-row outcomes are reported — nothing is silently skipped.

ParametersJSON Schema
NameRequiredDescriptionDefault
suggestionsYes

TDQS

A4.8/5.0
Behavior5/5

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

Annotations are bare (all false flags), so the description carries the full burden, and it delivers: every line is a pre-fill suggestion the owner must approve; invalid rows are rejected with named corrective data; stale allocations fill in nothing rather than a stale figure. Safety-relevant behaviors are stated explicitly and repeatedly ('never posts to the ledger', 'the one-tap Accept never applies'), consistent with readOnlyHint=false since it writes suggestions.

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 sentence carries substantive constraint information and the core purpose is front-loaded, but the ~850-word description is one unbroken paragraph with no hierarchy. The 'it never posts / owner decides' point is restated at least four times, and the standing-rule caveat is buried at the end, so an agent must parse a dense wall of text to find critical rules.

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 tool with six nested fields, intricate category-dependent conditionals, currency rules, and reference-data dependencies, nearly everything an agent needs is stated: ID source, valid category set, contact matching, the CARD_PAYMENT exception, allocation math with tolerance, and failure reporting ('Per-row outcomes are reported — nothing is silently skipped'). The only minor omission is the exact shape of the per-row outcome report, which the no-output-schema setup leaves the agent to infer.

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 0% and there are no per-property descriptions, so the description must supply all semantics — and it does, exhaustively: category must come from the review screen's set; contactName must match an existing contact exactly; accountCode is accepted only for OTHER/INTERNAL_TRANSFER and required for CARD_PAYMENT; allocations are limited to 20 items, only with contactName, in Ringgit, summing to the line within 0.10. It also encodes cross-field invariants the schema cannot express, such as the currency and outstanding-balance rules.

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+scope — 'Propose a category (and optionally a contact) for up to 50 imported bank rows still waiting for review' — and names bank_review_queue as the ID source. The PROPOSALS ONLY framing ('never confirms, never posts, nothing you send here moves money') cleanly separates this from the create_*_draft siblings that actually create documents.

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

Usage Guidelines5/5

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

Gives explicit when-to-use (rows still waiting for review, IDs from bank_review_queue) and when-not (already-decided CONFIRMED/POSTED/IGNORED rows are rejected). It names reference siblings as data sources — expense_accounts for the chart, open_invoices / ap_aging for open documents — and the standing-rule caveat tells the agent how to behave when the owner already has a rule.

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

employer_cost_estimateEmployer cost estimateA
Read-only
Inspect

Cost a HYPOTHETICAL hire: give a monthly wage and get back what that employee would really cost the employer each month — the wage plus employer EPF, SOCSO, EIS and the HRD Corp levy at this company's own rate — and what the employee would actually take home after employee EPF, SOCSO, EIS, SKBBK and PCB/MTD. Use it for "if I hire someone at RM4,000, what does it really cost me?" and "what would they take home?". Optional: residency (RESIDENT, the default, or NON_RESIDENT — a non-resident is taxed at a flat 30%), citizenship (MALAYSIAN or FOREIGNER — this drives the HRD Corp levy and makes SKBBK mandatory; it does NOT change the EPF, SOCSO or EIS rates applied, and it does not change tax residency, so set residency too), ageBand (UNDER_60 or 60_AND_OVER — reduced EPF and SOCSO Category 2), and epfEmployeeRate if the employee elects a reduced EPF rate. The PCB comes from Taokeh's implementation of LHDN's official computerised MTD method — the calculation IRBM confirmed in writing on 13 August 2026 (letter ref 2026-256) — not from a simplified formula. The defaults are RESIDENT, single, no children and NO TP1 reliefs, because reliefs are per-employee paperwork nobody has filled in for a person who does not exist yet; every assumption is spelled out in the reply and MUST be repeated to the user. Present it as an estimate on stated assumptions, never as a quote or as tax advice. READ-ONLY — it creates nothing, hires nobody and files nothing. ADMIN ONLY, like every payroll tool here.

ParametersJSON Schema
NameRequiredDescriptionDefault
ageBandNo
residencyNo
citizenshipNo
monthlyWageYes
epfEmployeeRateNo

TDQS

A4.4/5.0
Behavior5/5

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

The description goes well beyond the readOnlyHint annotation by stating it is READ-ONLY, creates/hires/files nothing, and is ADMIN ONLY. It discloses assumptions, defaults, that every assumption must be repeated to the user, and that the result is an estimate on stated assumptions. This is rich behavioral transparency.

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 description is dense and informative, but it is a single wall of text with long parentheticals and a very specific tax-authority reference. The main purpose is front-loaded, yet structure could be improved with clearer separation of purpose, parameters, defaults, and warnings.

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?

Despite no output schema, the description clearly indicates what the tool returns and under what assumptions. It covers defaults, key optional parameters, admin/read-only behavior, and the estimate nature. The main missing piece is `epfEmployeeRate`, which prevents full completeness.

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 0%, so the description carries the burden. It explains monthlyWage, residency, citizenship, and ageBand reasonably well, but it does not explain the `epfEmployeeRate` parameter at all—its units, default, or effect. This is a notable gap for an optional parameter that an agent might need to set.

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 immediately identifies the operation: cost a HYPOTHETICAL hire from a monthly wage, returning real employer cost and employee take-home. It names the specific payroll components and gives concrete example questions, making the tool's purpose unmistakable and distinct from actual payroll or document 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?

It explicitly says 'Use it for...' with concrete scenarios, and it provides when-not guidance ('never as a quote or as tax advice'). It also clarifies optional inputs like residency and citizenship, including when to set both. This is strong usage direction for an agent.

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

expense_accountsExpense accountsA
Read-only
Inspect

The expense accounts you can post to in this company — pick a category (what the money was for) and a paid-from account (where it came from) by code, for shaping a paid-expense draft. expenseCategories is a CURATED list: expense and asset accounts only, with cash/bank, the A/R and Inventory controls and contra accounts left out, because a cost never lands in one of those. A code outside this list is rejected when the draft is filed.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already convey readOnlyHint=true, and the description aligns with that by presenting this as a lookup/selection tool. It adds useful context about the returned data (categories, paid-from accounts, codes) and the company-specific scope, which is valuable given there is no output schema.

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

Conciseness5/5

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

A single sentence that front-loads the core identity ('The expense accounts you can post to in this company') and then elaborates with the precise selection information. Everything present earns its place, with no filler or 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?

For a zero-parameter, no-output-schema tool, this description is complete. It states what the tool returns (company postable expense accounts), what fields are available (category, paid-from, code), and the intended workflow (shaping a paid-expense draft).

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

Parameters4/5

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

The tool has zero parameters, so the baseline is 4. The description's mention of picking a category and paid-from account by code refers to the output content rather than input parameters, which is consistent with the empty 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 clearly identifies the resource: a list of expense accounts available for posting in this company. It specifies what can be picked (category and paid-from account) and by what identifier (code), distinguishing it from sibling tools like create_expense_draft or expenses_summary.

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

Usage Guidelines4/5

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

It provides a clear usage context: 'for shaping a paid-expense draft' tells an agent when to use this tool. However, it does not explicitly name alternatives or exclusion conditions, so it does not fully route the agent away from similar expense-related tools.

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

expenses_summaryExpenses summaryA
Read-only
Inspect

How much you have spent: your paid expenses today and this month so far.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only nature is known. The description adds useful context by specifying that only paid expenses are included and defining the time periods (today and month-to-date). It does not mention return format or any aggregation behavior, but that is less critical with annotations present.

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

Conciseness5/5

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

A single, front-loaded sentence conveys the purpose without any wasted words. It is appropriately concise for a simple zero-parameter 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 simple read-only summary tool with no parameters and no output schema, the description is reasonably complete. It covers the subject (paid expenses) and time range (today and month), though it leaves ambiguous whether the response is one total or two separate figures. This is a minor gap given the tool's simplicity.

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

Parameters4/5

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

The tool has zero parameters, and the schema is an empty object with 100% coverage. Per guidelines, the baseline for 0 params is 4, and the description does not need to add parameter details. It adds meaning by indicating the nature of the summary.

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

Purpose4/5

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

The description clearly states the tool reports how much the user has spent, specifically on paid expenses today and this month to date. It distinguishes from siblings like sales_summary and expense_accounts by mentioning 'paid expenses' and time ranges, though it lacks an explicit verb like 'get' or 'list'.

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

Usage Guidelines3/5

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

The description implies usage when the user wants a quick view of paid expenses for today and this month. It does not explicitly state when to use this tool versus alternatives such as search_expenses or expense_accounts, nor does it mention exclusions or prerequisites.

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

financial_timeseriesFinancial time series (monthly)A
Read-only
Inspect

A MONTH-BY-MONTH series of this company's figures across a window you name — the one call to make when you are asked to analyse a year or three years of trading. NEVER call income_statement 36 times and stitch the months together yourself: ask here once. You get, per month: revenue, cogs, grossProfit, opex, netIncome, cashClose, arClose, apClose and netCashMovement, in MYR. Give from and to as YYYY-MM (inclusive). The window is capped at 36 months — ask for a narrower window, or several windows, rather than expecting more. metrics narrows what is computed: any subset of pnl, cash, ar, ap, cashflow (default all); a metric you leave out has its fields OMITTED from every month, never returned as zero. THREE THINGS YOU MUST READ BEFORE YOU INTERPRET IT. First, a month that has not finished yet comes back with partial: true and a through date: its figures cover only the days up to and including that date — TODAY — and not the rest of the month, so they are month-to-date. Say so, and do not let the last point bend a trend. Second, months that ended BEFORE this company's accounting start date are left OUT OF THE SERIES, not zeroed: that history is still in the old system, and a note names the cutover date — this is a rule about the series, not about the ledger, because back-dating is allowed here, so a report run over an earlier window on /reports may still show stray entries before that date — and the month CONTAINING that date is partial: true with startsAt, because its trading only begins there; it is incomplete on the left the way a running month is on the right, never a weak month. Third, months that have not started yet are ABSENT too. An absent month is missing or unlived history, never a month with no business — never read one as a collapse in trading. EQUAL BASIS: every figure is produced by the same engine the web report uses for the exact dates stated (the month, or the month up to through when it is partial) — the P&L from /reports, cashClose from the cash-position liquid set (cash, banks, gateway clearing; owner advances and credit-card debt are not cash and are not in it), AR/AP from the aging reports' totals as of month end, netCashMovement from the cash-flow report's net. One caveat to carry: netCashMovement and the month-on-month change in cashClose are measured on DIFFERENT account sets, so they can legitimately differ — neither is a check on the other. ONE CALL ALSO HAS A TIME BUDGET: a very wide window with every metric can exceed it, in which case the call is REFUSED (it says how many months it managed) rather than answered with a short series — ask again for fewer months or fewer metrics. This tool returns FIGURES ONLY. It computes no ratios, no growth rates, no trend labels and no commentary — the reading is yours to write, from these numbers and the notes.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes
metricsNoWhich families of figures to compute. OMIT for all five; do not send an empty list. A family you leave out is omitted from every month, not zeroed.

TDQS

A4.9/5.0
Behavior5/5

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

The description is exceptionally transparent: it explains partial months with `partial: true` and `through`, absent months and the cutover rule, the equal-basis engine behind the figures, the netCashMovement vs cashClose discrepancy, the time-budget refusal behavior, and the fact that it returns figures only with no interpretation. The readOnlyHint annotation is consistent with this being a read-only computation 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 long, but the length is justified by the tool's many edge cases. It is well-organized into labeled sections (THREE THINGS YOU MUST READ, EQUAL BASIS, TIME BUDGET, FIGURES ONLY), which helps an agent parse the critical caveats. A few phrases could be tightened, but nothing is 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?

Despite having no output schema, the description names every field returned, explains how each is computed, clarifies partial/absent/cutover behavior, states currency, and documents failure modes. An agent has everything needed to interpret the response correctly and avoid common misinterpretations.

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 only 33%, so the description carries the burden for `from`/`to` and it does: YYYY-MM format, inclusive, 36-month cap, and MYR currency. For `metrics`, it adds that leaving a metric out omits those fields entirely and never zeroes them, going beyond the schema's basic enum description.

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 clear, specific statement: a month-by-month series of company figures across a user-named window. It also differentiates itself from income_statement by explicitly saying to request this once instead of stitching 36 months together, making the tool's role 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?

The description gives direct when-to-use guidance: use this for analyzing a year or three years of trading, and never call income_statement 36 times. It also advises asking for narrower windows or fewer metrics when the time budget is exceeded, covering the main alternative and constraint behavior.

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

find_in_taokehFind in TaokehA
Read-only
Inspect

A FEATURE FINDER, NOT A RECORD SEARCH. It searches Taokeh's own SCREENS, FEATURES and SETTINGS — never the books. Use it to tell the user WHERE in Taokeh to do something or change a setting: it returns the exact page(s) and what each one does, grounded in Taokeh's LIVE feature catalogue, so you never guess or invent navigation. ⛔ It does NOT look up documents, invoices, customers, products or any other RECORD, and it cannot tell you it failed to — a document number, a customer's DO/PO number, a person's name or an amount typed in here will still rank some page (the closest-worded screen), and that page will be a wrong answer wearing a right one's clothes. Records live elsewhere: search_documents (invoices, credit notes, quotes, delivery orders, bills, POs — and a customer's own Ref No), search_expenses (posted paid expenses), search_journal (ledger entries), resolve_customer / resolve_vendor / resolve_product (a named party or item), open_invoices (what one customer owes). Give a natural-language query about a CAPABILITY ("where do I turn on payment reminders", "how do I connect Shopee", "where's the SST setting") and it ranks the real features and hands back the top matches, each with the page's absolute deep-link URL(s), a one-line description of what the page does, an optional configHint (Taokeh keeps a feature's options on its OWN page, not in a global Settings menu), and an addOn flag (a paid add-on this company may not have). It GUIDES to the UI only — it changes nothing: no setting is ever toggled by the connector, that stays a human action in-app. If nothing matches it says so honestly — then tell the user to browse the left sidebar or contact support; never make up a path.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryNoWhat the user wants to DO or the setting they want to CHANGE, in words — not a document number, a customer name or an amount (those are records; use search_documents / resolve_customer instead).

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, and the description reinforces and extends this: 'It GUIDES to the UI only — it changes nothing: no setting is ever toggled by the connector.' It also discloses a critical failure mode: record-like queries will still rank a page and thus produce a plausible but wrong answer. This is valuable behavioral context beyond the annotations. No contradiction.

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

Conciseness4/5

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

The description is front-loaded with the most important distinction and every section adds useful information. However, it is quite long, with some repetition (e.g., 'never the books' and later 'does NOT look up documents'), and the vivid 'wrong answer wearing a right one's clothes' phrasing is stylistic rather than essential. Still, the length is largely justified by the high risk of misuse.

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?

Even though there is no output schema, the description thoroughly documents the return shape: ranked feature matches with exact deep-link URLs, one-line descriptions, configHint, and addOn flag. It covers failure behavior, scope limits, alternatives, and the safety guarantee. An agent has everything needed 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?

The schema already provides 100% coverage for the single `query` parameter with a clear description. The tool description adds extra semantic guidance: it gives concrete examples ('how do I connect Shopee'), reiterates what not to type, and explains how the query is used to rank features. This goes beyond the schema description, though the schema already does substantial work.

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 clear, specific statement: 'A FEATURE FINDER, NOT A RECORD SEARCH.' It names the exact resource (Taokeh's screens, features, settings), the action (find/guide to UI), and explicitly distinguishes itself from record-search tools. This fully separates it from siblings.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance (capability questions like 'where do I turn on payment reminders') and when-not-to-use guidance (records, document numbers, customer names). It names direct alternatives: search_documents, search_expenses, search_journal, resolve_customer/vendor/product, and open_invoices. It also provides fallback behavior when nothing matches.

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

get_attachmentGet original document linkA
Read-only
Inspect

Get a short-lived link to the ORIGINAL DOCUMENT filed against something in the books — the receipt behind a posted expense, or the receipt/sales note/supplier bill/bank-in slip/name card riding a PENDING draft. Use it to CHECK a document is on file, or to re-read one you filed earlier. Find what to ask for first: search_expenses reports hasAttachment and an attachments list (with an attachmentId) on every posted expense it returns, and each create_*_draft / revise_draft result reports whether an original rides that draft. Give owner plus the id of the thing that owns it — for a posted expense that is the expenseId from search_expenses, plus the attachmentId when the entry carries more than one file; for a draft it is the draftId. Returns a signed URL (about 15 minutes, works for anyone holding it — so treat it as you would the document itself), the filename, the media type and the size in bytes; the bytes themselves are NEVER inlined here, because a base64 blob in a tool result costs about one token per character. Download it and read it yourself: Taokeh does not read, OCR or interpret the file for you — your own AI does that, on your own subscription. Read-only; it changes nothing, emails nobody, and no link it hands out can reach another company. An APPROVED draft honestly reports no original: on approval the file moves onto the posted document, so ask for it there instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe owner's id — the expenseId from search_expenses for 'expense', otherwise the draftId a create_*_draft or revise_draft call returned.
ownerYesWhat the original hangs off: 'expense' = a POSTED paid expense (use the expenseId from search_expenses); 'expense_draft' / 'invoice_draft' / 'bill_draft' / 'quote_draft' / 'receipt_draft' / 'payment_draft' / 'contact_draft' = a PENDING draft (use its draftId); 'shoebox' = a photo someone in the business sent in from their phone and nobody has read yet (use the id from shoebox_items).
attachmentIdNoWhich file, when a posted expense carries more than one — the `attachmentId` from that expense's `attachments` list in search_expenses. Omit for a draft (a draft carries at most one original), and omit for an expense with exactly one file.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses the signed URL expiry and sharing properties, that bytes are never inlined (with token-cost rationale), that Taokeh does not OCR or interpret the file, and that the operation has no side effects. It also confirms there is no contradiction with the annotation.

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

Conciseness4/5

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

The core purpose and usage are front-loaded, and each sentence carries real information. The description is somewhat long for a simple read-only link tool, with a few rhetorical embellishments, but the length is justified by the many owner varieties and edge cases.

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 covers the return contract (signed URL, filename, media type, size, no inline bytes), security posture, owner/draft edge cases, and read-only behavior. An agent has all information needed to call it correctly and interpret the result.

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?

Although schema coverage is 100%, the description adds crucial semantic detail: how to obtain the owner/id values from prior tool results, when attachmentId must be supplied, and when it must be omitted. This goes well beyond the schema's enum and type descriptions.

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 the tool gets a short-lived link to the ORIGINAL DOCUMENT filed against an expense or draft, which is a precise verb+resource. It also clarifies what counts as a document in each state, distinguishing the lookup target from other operations like get_document_pdf.

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 explicitly says when to use it ('CHECK a document is on file, or re-read one you filed earlier'), where to find the required ids (search_expenses and create_*_draft/revise_draft results), and when not to ('An APPROVED draft honestly reports no original... ask for it there instead'). This is clear routing guidance with no reliance on inference.

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

get_document_pdfGet document PDF linkA
Read-only
Inspect

Get a shareable link to the ACTUAL PDF of one invoice, quote or credit note — so you can hand the user (or their customer) the real document, e.g. "here's your invoice". Identify the document by its docId (from search_documents) OR its printed docNumber (e.g. the invoice number) — give one; if a number matches several documents I'll list them so you can pick the id. Returns a short-lived signed URL (works for ~15 minutes, for anyone who has it — so share it deliberately), the document number, and when it expires. Covers invoices, quotes and credit notes (they share one document layout). This does not email anyone — it hands YOU a link to pass on.

ParametersJSON Schema
NameRequiredDescriptionDefault
docIdNoThe document id (from search_documents). Give this or docNumber.
docTypeYesWhich document: 'invoice', 'quote' or 'credit_note'.
docNumberNoThe printed document number (e.g. the invoice/quote reference). Give this or docId; resolved case-insensitively and must match exactly one document.

TDQS

A4.5/5.0
Behavior5/5

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

The description adds rich behavioral context beyond the readOnlyHint annotation: the returned URL is short-lived (~15 minutes), shared-access means anyone with it can use it, and sharing should be deliberate. It also discloses that multiple matches will be listed for the user to pick, and clarifies that this tool does not send emails. This is exemplary transparency.

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

Conciseness5/5

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

The description is front-loaded with the core purpose, then systematically covers identification, return value, expiry, scope, and non-email behavior. Every sentence adds relevant information, and the structure makes the tool's behavior easy to parse for an agent.

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 there is no output schema, the description carries the full burden of explaining return values, and it does so explicitly: the signed URL, the document number, and expiration time are all mentioned. It also covers document coverage and disambiguation behavior, making the tool's behavior complete for an agent invoking it.

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?

With 100% schema description coverage, the schema already documents all three parameters clearly. The description reinforces the relationship between docId and docNumber ('give one') but does not add significant new semantics beyond what the schema provides. This meets the baseline but does not exceed 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 description opens with a specific verb and resource: 'Get a shareable link to the ACTUAL PDF of one invoice, quote or credit note'. It clearly distinguishes the tool from generic document tools by emphasizing the real PDF artifact and explicitly noting it does not email anyone. This makes the purpose unmistakable.

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 provides clear when-to-use context: when you need to hand the user or their customer the actual document. It explains the two identification paths (docId from search_documents or printed docNumber) and the disambiguation behavior if multiple matches occur. It stops short of explicitly naming alternative tools for when not to use it, but the guidance is still strong.

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

import_bank_statementImport bank statement into the review queue (nothing posts)AInspect

Import a bank statement into Taokeh for reconciliation, from a statement you've read (PDF/CSV/image). This does NOT post to the books — every row lands in Banking → Review for the user to categorize and post line by line. A statement is the bank's own list of transactions for ONE account over a period: use intake_contract(doc_type:'statement') first to see the tenant's bank accounts + the arithmetic law. Give the account id, the printed opening + closing balances, and every transaction row (signed amount: + money in, − money out). The server checks opening + the rows tie to the closing balance and rejects with the exact delta if they don't — never invent or omit rows to force it to balance. CREDIT CARDS: a card statement can be filed here too, but ONLY with signConvention declared, because a card prints the opposite convention (a purchase INCREASES what you owe). Pass 'PRINTED_CARD' when the figures are exactly as the card statement prints them (the usual case) or 'STORED' if you deliberately converted them to Taokeh's convention (− = a spend). Never guess: declaring the wrong one books the whole month backwards and the arithmetic check cannot catch it, because negating every figure still ties out — the server runs a separate directional check and refuses a declaration that reads as a card which never owed anything. signConvention is refused on a bank account. Each card line is then expensed on its OWN statement date against the card, and the "payment received" line that settles the card bill is excluded automatically (the bank statement's lump owns that movement). Single receipts, invoices or bills go through their own draft doors, not here. ARCHIVING THE ORIGINAL: this import archives the statement file WHEN you send one — call request_attachment_upload FIRST, PUT the statement's raw bytes to its uploadUrl, then pass the returned attachmentToken here; the original is then kept on the statement (s.82 record-keeping) and the user can download it from the statement page, exactly as the web upload at Banking → Import does. Without a token nothing is archived and the books carry rows with no source document behind them. Already filed one bare? Call this tool AGAIN with the IDENTICAL account, balances and rows plus attachmentToken — the identical reading matches the same statement, so the file is ADOPTED onto it and no rows are staged twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
rowsYes
bankAccountIdYes
closingBalanceYes
confirmOverlapNoSet to true ONLY after the user has confirmed this is a genuinely new, separate statement whose period overlaps one already imported. It bypasses the overlap guard that stops the same transactions being counted twice. Never set it to push an overlap through — ask the user first.
openingBalanceYes
signConventionNoREQUIRED when bankAccountId is a CREDIT CARD, and refused on a bank account. Which convention you signed the rows AND the opening/closing balances in. 'PRINTED_CARD' = exactly as the card statement prints them: a purchase is POSITIVE (what you owe goes up), a payment or refund is NEGATIVE, and the balances are the printed balances owed — this is the right choice when you read the card's own statement. 'STORED' = already converted to Taokeh's stored convention: a spend is NEGATIVE, a payment or refund POSITIVE, and the balances negative while money is owed. Do not guess between them: the wrong declaration books the entire month backwards, and the arithmetic check cannot catch it because negating every figure still ties out. Ask the user if unsure.
attachmentBytesNoThe decoded byte size of the ORIGINAL file on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing a corrupt file.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the statement bytes to its uploadUrl. This is the normal way to archive a statement PDF — it carries the file out-of-band (no base64 in this call). Mutually exclusive with attachmentBase64. The file is archived on the statement and the user downloads it from the statement page in Taokeh.
attachmentBase64NoThe ORIGINAL statement as base64 — SMALL files only (a few KB). A real bank statement PDF is never that small, so in practice use request_attachment_upload + attachmentToken instead. Mutually exclusive with attachmentToken. A bad type/oversize file is rejected and NOTHING is imported.
attachmentSha256NoThe SHA-256 of the ORIGINAL file as 64 hex chars — optional second check alongside attachmentBase64, so corrupted bytes are rejected instead of filed.
attachmentFilenameNoThe original filename, for the user browsing their statements.
attachmentMediaTypeNoThe attachment's MIME type, e.g. 'application/pdf'. Required when attachmentBase64 is given.
confirmSignConventionNoSet true ONLY after the user confirms that the card genuinely sat in CREDIT for the whole period. It bypasses the directional check that refuses a statement reading as a card which never owed anything — the usual cause of which is a printed statement declared 'STORED' (or the reverse). Never set it to push a refusal through: ask the user first.

TDQS

A5/5.0
Behavior5/5

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

The description adds substantial behavioral context beyond the annotations: it clarifies that nothing posts to the books, that the server validates opening balance plus rows against closing balance and rejects with the exact delta, that a wrong signConvention can pass arithmetic but fail a directional check, and that the card settlement line is excluded automatically. It also details attachment archiving behavior and idempotent adoption on identical re-import. No contradiction with annotations.

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

Conciseness5/5

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

The description is long but every substantial section earns its place: overview, credit-card convention warning, and archiving workflow. It is front-loaded with the core behavior, then organized into distinct paragraphs that group related warnings and operational steps. The length is justified by the high-risk failure modes and the number of 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?

For a tool with 13 parameters and no output schema, the description is remarkably complete: it covers prerequisites, arithmetic validation, sign-convention directional checks, per-line expensing behavior, attachment upload flow, and the re-import adoption path. A return-shape specification would be a nice addition, but the operational context needed to invoke this tool correctly is fully present.

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?

Even though schema coverage is 69%, the description adds essential meaning for the most nuanced parameters: signConvention is explained with two concrete interpretations and the refusal rule for bank accounts, attachmentToken and attachmentBase64 are positioned with mutual exclusivity and practical guidance, and rows are defined as signed amounts. This goes well beyond what the schema supplies.

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 and resource: 'Import a bank statement into Taokeh for reconciliation.' It clearly scopes the tool to statement imports that land in Banking → Review, and explicitly contrasts it with sibling doors: 'Single receipts, invoices or bills go through their own draft doors, not here.' This makes it easy to distinguish from create_bill_draft, create_invoice_draft, and other draft 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?

The description gives explicit usage prerequisites: 'use intake_contract(doc_type:''statement'') first to see the tenant's bank accounts + the arithmetic law.' It also states when not to use the tool, names alternative doors for other documents, and explains the re-import workflow for adopting an attachment onto an already filed statement. This is concrete, actionable routing guidance.

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

income_statementIncome statementA
Read-only
Inspect

Your profit and loss for a period: revenue, cost of goods sold, gross profit, expenses and net income. COMPARISON (optional): to answer "how does this month compare with last?" ask for it here — NEVER call this tool twice and subtract the figures yourself. Set compare to 'previous_period' (the window of EQUAL LENGTH immediately before this one) or 'same_period_last_year' (the same dates one year earlier), OR give an explicit earlier window with BOTH compareFrom and compareEnd. You get both periods' full statements plus, for every account line and every total, deltaCents and deltaPct computed server-side in integer cents. deltaPct is NULL whenever the earlier figure is zero — a percentage change from zero is undefined, so report it as "no comparable base", never as ∞% or 100%. Percentages are measured against the ABSOLUTE earlier figure, so a movement out of a loss keeps the sign of the movement. windows states both windows, each one's day count, whether they are the same length, and whether either is still open (running to today or beyond, so its figures can still move); notes says all of this in plain words. READ notes BEFORE quoting a variance: if equalLength is false you are looking at a partial period against a full one and must say so.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes
compareNoNamed comparison window. 'previous_period' = the equal-length window immediately before from…to; 'same_period_last_year' = the same dates one year earlier. Omit for no comparison.
compareEndNoEnd of an explicit comparison window (use WITH compareFrom).
compareFromNoStart of an explicit comparison window (use WITH compareEnd; overrides `compare`).

TDQS

A5/5.0
Behavior5/5

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

Annotations already indicate read-only, but the description adds substantial behavioral context beyond that: it explains that comparison returns deltaCents and deltaPct computed server-side, details about deltaPct being NULL when the earlier figure is zero, how percentages are measured, and the structure of the `windows` and `notes` fields. No contradictions with annotations.

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

Conciseness5/5

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

The description is front-loaded with the core purpose in the first sentence. Every subsequent sentence earns its place by explaining comparison behavior, return fields, and edge cases. Despite being longer, the structure is logical and all content is necessary for correct tool usage.

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 5 parameters (2 required), no output schema, and moderate complexity, the description provides complete coverage. It explains the output structure (deltaCents, deltaPct, windows, notes), handles edge cases (NULL deltaPct, unequal window lengths), and gives usage instructions. No gaps are apparent.

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?

Despite 60% schema description coverage, the description adds significant meaning to all five parameters. It explains the purpose of `from` and `to` as the primary period, details the `compare` enum options with clear definitions, and explicitly states that `compareFrom`/`compareEnd` must be used together and override `compare`. This fully compensates for schema gaps.

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

Purpose5/5

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

The description clearly states it provides profit and loss for a period, listing major line items (revenue, COGS, gross profit, expenses, net income). This distinguishes it from sibling tools like balance_sheet or cash_forecast by specifying the exact financial statement. The verb 'your profit and loss' is specific and the resource is well-defined.

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

Usage Guidelines5/5

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

The description explicitly states when to use the comparison feature and, crucially, tells the agent NEVER to call the tool twice and subtract manually. It provides clear instructions on setting the `compare` parameter or using explicit `compareFrom`/`compareEnd`. It also warns to read `notes` before quoting a variance and explains how to handle unequal length windows.

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

intake_contractIntake contractA
Read-only
Inspect

The shape a Taokeh document needs, so you can turn a paid receipt, a sales note, a supplier bill, a customer payment, a payment you made to a supplier, a sales return, a bank statement or a whole set of OPENING BALANCES into a correctly-formed submission: required fields, how to read totals / measurements / SST, and a worked example grounded in this company. Pass doc_type 'expense' (default), 'invoice', 'bill', 'purchase_order', 'statement', 'receipt', 'payment', 'credit_note', 'sales_debit_note', 'journal', or — when this company is SWITCHING from another accounting system — 'historical_document' (ONE already-issued invoice or supplier bill being brought across in bulk with stage_document), 'trial_balance', 'aged_receivables' or 'aged_payables', which are staged in one call each with stage_opening_balances, and 'accounts', 'products', 'contacts', 'settings' or 'employees' (its CHART OF ACCOUNTS, its item list, its customer/supplier book, its COMPANY SETUP and its STAFF LIST), which are staged in one call each with stage_master_data — do 'accounts' first, since the trial balance matches against the chart. The 'settings' contract lists every stageable key, its meaning and current value, plus every owner-only setting the AI may never write and the reason/page for each. The 'employees' contract is ADMIN-ONLY. Nothing posts on its own — the user reviews everything in Taokeh.

ParametersJSON Schema
NameRequiredDescriptionDefault
doc_typeNo

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 openWorldHint=false. The description adds behavioral context beyond that: users review everything in Taokeh, employees is admin-only, and settings includes owner-only values the AI may never write. It does not mention output shape or potential size/performance, but for a reference tool this is solid.

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 information-dense and front-loaded with the core purpose. Each section earns its place: required fields, doc_type categories, staging functions, ordering, permissions, and non-posting behavior. It is not redundant, though the long doc_type list could arguably be trimmed for conciseness without losing much value.

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

Completeness5/5

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

Given the simple schema (one optional parameter), no output schema, and read-only annotations, the description covers everything needed: what the contract contains, the full set of doc_type values, how each is staged, ordering constraints, permission caveats, and the non-posting guarantee. It is complete for an agent to select and invoke the tool appropriately.

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 0%, so the description carries the burden. It enumerates all valid doc_type values and explains their meaning, including special categories for opening balances and master data, plus the associated staging functions. It does not explicitly state that doc_type is a string, but it fully describes the accepted values and their 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?

The description clearly states what intake_contract does: it returns the shape a Taokeh document needs, listing supported doc_type values, the intended source documents, and how the contract maps to staging functions. It distinguishes itself from sibling draft/staging tools by framing this as a reference/contract tool, not an execution tool.

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

Usage Guidelines5/5

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

The description explicitly explains when to use this tool: before staging documents, opening balances, or master data. It gives specific doc_type values, instructs to do 'accounts' first, notes the employees contract is admin-only, and says nothing posts on its own. This is strong, actionable guidance that clearly routes the agent to the correct usage.

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

low_stockLow stockA
Read-only
Inspect

Which products are at or below their reorder point right now — the "what do I need to reorder" list. Each row: sku, name, on-hand quantity, reorder point and unit. Capped, with the true count so you know if more exist. Uses the same rule as the dashboard low-stock chip (reorder point set AND on-hand ≤ reorder point). If this company uses Counter (the till), quantities are as at the last day-close: counter sales move stock once, when the day is closed, so an open trading day shows more on hand than the shelf does.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, and the description adds substantial behavioral detail beyond that: results are capped but include the true count, the matching rule matches the dashboard chip, and Counter quantities are as at day-close so an open trading day overstates shelf stock. No contradiction with annotations.

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

Conciseness5/5

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

The description is compact yet complete: purpose, row shape, cap behavior, matching rule, and a critical timing caveat are each given in one well-placed sentence. No filler or repetition.

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 of explaining return values, and it does: it lists the fields per row, states that results are capped with a true count, and clarifies the reorder rule and Counter timing. This is sufficient for an agent to know what to expect and how to interpret the data.

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

Parameters4/5

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

The tool has zero parameters and schema coverage is 100% by virtue of an empty schema, so the baseline is 4. There is no parameter-level information to add, and the description appropriately focuses on outputs and behavior instead.

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

Purpose5/5

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

The description opens with a precise verb and resource: 'Which products are at or below their reorder point right now' and labels it the 'what do I need to reorder' list. It further specifies the exact filtering rule and output fields, distinguishing it clearly from siblings like stock_level and stock_movements.

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 strong contextual cues: it is a current reorder snapshot, capped with a true count, and aligned with the dashboard low-stock chip. It explains the Counter day-close timing caveat that affects interpretation. It does not explicitly name alternatives or state when not to use it, but the context is clear enough for an agent to select it appropriately.

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

my_workMy workAInspect

YOUR OWN QUEUE in this company, in one call — what you filed and what happened to it. Answers four questions: (1) PENDING — everything of yours still waiting on the owner's approval, across every lane (expense, invoice, bill, quote, receipt, supplier payment, contact, credit note, debit note, purchase order, adjusting journal, your bank-category proposals), each with its reference, party, amount, how many days it has waited, and the exact next step in words plus the owner's review link; (2) APPROVED — what the owner approved since since (default: the last 7 days) and WHAT IT BECAME, with the posted document's own reference, so you can say "that one is now invoice INV-0042"; (3) REJECTED — what the owner or the engine refused, with the reason VERBATIM whenever one is stored. Every reject door in Taokeh offers the owner an optional "Why?" box, and staged migration rows carry the engine's own refusal text; where a reason is present, reason holds those exact words and reasonRecorded is true — READ IT and fix precisely what it names rather than re-filing the same thing. The box is never compulsory, so a refusal with an empty box reports reason: null and reasonRecorded: false; read that as "unknown", ask the owner what was wrong, and do NOT guess why before re-filing; (4) STAGED — your migration work (historical documents, opening balances, master data) sitting at a commit door. Params: since (YYYY-MM-DD or ISO, optional), kind (optional single-lane filter), limit (default 50, max 200 — every bucket reports total, returned and an honest truncation note; nothing is silently dropped). READ-ONLY. It changes nothing, it cannot approve anything, no tool can approve on the owner's behalf, and no tool of any kind moves money — every pending item is one human tap in Taokeh.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNo
limitNo
sinceNo

TDQS

A3.8/5.0
Behavior1/5

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

The description explicitly claims "READ-ONLY. It changes nothing," but the annotations set readOnlyHint to false. This is a direct contradiction between the descriptive text and structured metadata. Per the rubric, a contradiction forces a score of 1, despite the description otherwise containing rich behavioral detail.

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

Conciseness3/5

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

The description is front-loaded with core purpose and uses numbered sections, which is good structure. However, it is verbose and repetitive, repeating the read-only point multiple times ("READ-ONLY", "It changes nothing", "it cannot approve anything", "no tool can approve on the owner's behalf"). It would benefit from tightening.

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 tool with no output schema, the description thoroughly explains what will be returned in each bucket: pending items with reference, party, amount, wait time, next step, and review link; approved items with the resulting posted document reference; rejected items with verbatim reasons and `reasonRecorded` semantics; and staged migration work. It leaves no critical operational gap.

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?

With 0% schema description coverage, the description fully compensates: it specifies `since` as YYYY-MM-DD or ISO with a 7-day default, `kind` as an optional single-lane filter, and `limit` with default 50, max 200, and honest truncation behavior. It adds practical meaning that the sparse schema alone does not provide.

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, concrete purpose: "YOUR OWN QUEUE in this company, in one call — what you filed and what happened to it." It enumerates four distinct status questions (PENDING, APPROVED, REJECTED, STAGED), making the tool's role unmistakable and distinguishing it from sibling report/review 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?

It gives clear context for when to use the tool: the user wants one consolidated view of their own filed items across all lanes, including approvals since a date and migration items. It does not explicitly name alternatives or exclusion conditions (e.g., 'use bank_review_queue instead when...'), 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.

open_invoicesOpen invoicesA
Read-only
Inspect

The unpaid (or part-paid) invoices for one customer, oldest first — search by customer name.

ParametersJSON Schema
NameRequiredDescriptionDefault
customerYes

TDQS

A4.2/5.0
Behavior3/5

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

readOnlyHint=true already signals a safe read operation. The description adds that results are unpaid/part-paid, oldest first, and filtered by customer name. It does not describe returned fields, but with annotations covering safety, this is acceptable.

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

Conciseness5/5

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

The description is a single, front-loaded sentence with no filler. Every phrase adds value: unpaid/part-paid, one customer, oldest first, search by name.

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 simple one-parameter, read-only tool with no output schema, the description sufficiently covers scope, ordering, and search key. It does not enumerate return fields, which might be useful but is not critical for tool selection.

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 has zero description coverage for the single 'customer' parameter. The description compensates by explaining it is a customer name, which is essential for correct invocation and adds meaning beyond the raw schema type.

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

Purpose5/5

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

The description clearly states it returns unpaid/part-paid invoices for a single customer, ordered oldest first, searchable by customer name. This distinguishes it from aggregate tools like ar_aging or search_documents.

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 implies use when needing open invoices for one customer and specifies search by customer name. It does not explicitly name alternative tools or exclusion scenarios, but the scope is clearly constrained to a single customer, providing adequate context.

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

payer_historyPayer historyA
Read-only
Inspect

How this company has treated a given bank counterparty (a payer or payee, named as printed on the statement line) before: the historical bank rows a human already CONFIRMED or POSTED for that name — grouped by category, contact and GL account, with a count, date range and total amount each — plus the live suggestion Taokeh would now make for it. That live suggestion carries a basis: 'LEARNED' means it was worked out by tallying those confirmed rows, and timesSeen says how many; 'OVERRIDE' means the OWNER has written a standing rule for this payer on the memory page (What Taokeh has learned → Bank rules), which BEATS the tally — ruleSetOn is the date they set it, and timesSeen is 0 because a rule was never "seen" any number of times. Never report an override as history: the owner said so, the books did not. This is the tenant-scoped PRECEDENT behind a suggestion, so you can explain WHY a row is being categorized a certain way. READ-ONLY; the owner still confirms every categorization in Taokeh.

ParametersJSON Schema
NameRequiredDescriptionDefault
counterpartyYes

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description explains the non-obvious behavioral distinction between LEARNED and OVERRIDE bases, what timesSeen and ruleSetOn mean, and explicitly warns not to report an override as history. This is exactly the kind of subtle behavioral context an agent needs to avoid misreporting 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?

The description is long but information-dense, and every clause contributes to understanding a genuinely complex return value. It front-loads the core purpose and then unpacks the LEARNED/OVERRIDE semantics, with the warning placed near the end for emphasis. Slightly verbose, but earned.

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 fully compensates by specifying the grouping fields, aggregates, basis values, timesSeen, ruleSetOn, and the tenant-scoped nature. It also includes the critical caveat about overrides, making the tool safely invokable and interpretable without additional context.

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

Parameters4/5

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

With 0% schema description coverage, the description carries the parameter burden and delivers: counterparty is defined as a payer or payee named as printed on the statement line. This is more meaningful than the raw schema's minLength constraint, though it could add a bit more on matching or formatting expectations.

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

Purpose5/5

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

The description clearly defines what the tool returns: historical confirmed/posted bank rows for a counterparty, grouped by category/contact/GL account, plus the live Taokeh suggestion with its basis. This distinguishes it from sibling tools like resolve_vendor or search_document_lines because it centers on precedent for categorization, not entity resolution or document search.

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 states its intended use: it is the tenant-scoped precedent behind a suggestion, so an agent can explain WHY a row is categorized a certain way. It gives clear context, but does not explicitly name alternatives or state when not to use it, 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.

payroll_summaryPayroll summaryA
Read-only
Inspect

A month's payroll from gross to net, as it was actually run: total gross (basic, allowances, overtime, public-holiday pay and any bonus), what was deducted from staff (EPF, SOCSO, EIS, SKBBK, PCB/MTD, zakat), what the employer contributed on top (EPF, SOCSO, EIS, HRD Corp levy), the total net pay, and the employer's TRUE total cost for the month — wages plus every employer contribution. Also lists who is on approved leave in the next 14 days, so "what does payroll look like this month" and "who is out next week" are one call. With no month it reads the latest FINALIZED or POSTED run; give a month as YYYY-MM for a specific one. Set perEmployee: true for the per-person breakdown — those are individual salaries, so ask for them only when the user actually wants them; each entry carries that person's real employeeId. Set staff: true for the full employee ROSTER with ids, which works even when payroll has never been run — that is where the employeeId for update_employee_draft comes from, and it is the only place an id is published: never key an employee by name. Every figure is a sum of the STORED payslips of that run — the same numbers the staff were paid on and the payroll journal was posted from — never a recalculation. If nothing has been run, it says so plainly rather than returning a month of zeros. ADMIN ONLY: payroll sits behind its own role in Taokeh and this tool refuses on any other connection. READ-ONLY — it cannot create a run, pay anybody, or file anything with LHDN, KWSP or PERKESO.

ParametersJSON Schema
NameRequiredDescriptionDefault
monthNo
staffNoReturn the full employee ROSTER (id, name, staff no., status, designation, basic salary) alongside the summary — independent of any run, so it works even before the first payroll. This is where the employeeId for update_employee_draft comes from. Individual salaries: ask for it only when the user actually needs it.
perEmployeeNo

TDQS

A4.8/5.0
Behavior5/5

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

The readOnlyHint is reinforced and expanded: the tool 'cannot create a run, pay anybody, or file anything.' It also discloses behavioral edge cases: it reads the latest FINALIZED or POSTED run, returns a plain statement if nothing has been run rather than zeros, and enforces an ADMIN ONLY role requirement. These go far beyond 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?

The description is long but every sentence adds functional or safety-relevant information, and the most important user-facing behavior is front-loaded. The final ADMIN/READ-ONLY warning is appropriately placed at the end.

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-only summary tool with no output schema, the description comprehensively covers return semantics, parameter behavior, permission constraints, and edge cases. The only missing piece is exact response structure, but that is unnecessary given the detailed narrative and the tool's simple boolean/string parameters.

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 only 33% because month and perEmployee lack schema descriptions, but the description compensates thoroughly: month format YYYY-MM and behavior when omitted, perEmployee's sensitivity and employeeId detail, and staff's independent-of-run behavior and link to update_employee_draft. Only a small amount of redundancy with the staff schema description remains.

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 and resource ('A month's payroll...') and enumerates exactly what is included: gross, deductions, employer contributions, net pay, and true total cost. It also distinguishes itself from sibling tools by clarifying payroll-specific outputs and pointing to update_employee_draft for employee IDs.

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

Usage Guidelines5/5

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

The description explicitly tells when to use it ('what does payroll look like this month' and 'who is out next week'), when to set perEmployee and staff, and warns to request per-employee salaries only when genuinely needed. It also contrasts with alternatives like employer_cost_estimate by clarifying this is actual stored payroll, not a recalculation.

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

profit_driversProfit driversA
Read-only
Inspect

The DIAGNOSTIC breakdown of WHY net profit moved — deterministic, not a model's arithmetic. Compares the current month-to-date against the SAME day-span of the previous month (day 1 through min(today's day, the prior month's last day)), so a partial month is never compared against a full one. Returns: the net-profit figure for both windows and the delta; a drivers bridge (revenue delta, COGS delta, then the operating-expense accounts that moved most — top 5 by absolute change plus an other roll-up); oneOffs (disposal and FX gains/losses, pulled out of the movers so a lumpy asset sale doesn't read as an operating trend — empty if you have no such accounts); the prior month's FULL-month net profit as a stated secondary reference (priorMonthFull); and an assumptions list. Each driver's direction is its effect on PROFIT ('improving'/'worsening'/'flat'). All amounts are integer CENTS (RM = cents ÷ 100). Optional month (YYYY-MM) picks a month other than the current one — a completed past month compares its whole length; omit for the current month-to-date.

ParametersJSON Schema
NameRequiredDescriptionDefault
monthNoMonth to analyse, YYYY-MM. Omit for the current month-to-date.

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the read-only annotation, the description adds rich behavioral details: deterministic computation, specific period comparison, handling of one-offs, cents units, and behavior for optional month. This goes well beyond what annotations convey, giving the agent a thorough understanding of the tool's behavior.

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

Conciseness5/5

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

The description is long but every sentence adds value, covering purpose, methodology, return fields, and parameter semantics. It is front-loaded with the core purpose and structured logically, making it easy to process despite 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?

With no output schema, the description thoroughly explains all return components, units, and the behavior of the optional month parameter. It is complete for a tool of this complexity, covering all necessary context for an agent to invoke 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% for the single optional parameter, but the description adds meaningful behavior beyond the schema: it explains that for a completed past month, the whole month is compared, and for the current month it uses month-to-date. This enriches the parameter's meaning.

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

Purpose5/5

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

The description clearly states it is a diagnostic breakdown of why net profit moved, using specific verbs and a defined resource. It also distinguishes itself from sibling tools by emphasizing the deterministic comparison logic and the focus on profit drivers, which is unique among the listed siblings.

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

Usage Guidelines4/5

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

The description provides clear context for when to use the tool, explaining the comparison methodology and return values. However, it does not explicitly mention when not to use it or point to alternative tools (e.g., income_statement), so the guidance is strong but not fully explicit.

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

request_attachment_uploadRequest attachment uploadAInspect

Get a one-time link to upload a receipt/bill/statement/document that is too large to inline as attachmentBase64 (a real photo or a multi-page PDF — base64 inside a tool call is very costly). Returns an uploadUrl and an attachmentToken: PUT the file's RAW bytes to uploadUrl within the time limit, then pass attachmentToken IN PLACE OF attachmentBase64 to create_expense_draft / create_invoice_draft / create_bill_draft / create_quote_draft / create_receipt_draft / create_contact_draft / create_journal_draft — the file rides that draft and lands on the posted document on approval, exactly as an inline attachment does — or to import_bank_statement, which archives it as the statement's original. CALL THIS FIRST, BEFORE the create/import call: filing bare and adding the file after is the harder path. If you DID already file bare, the repair on the five document lanes (expense, invoice, bill, quote, receipt) is to call the same create tool AGAIN with the IDENTICAL reference + date + amount plus attachmentToken — while the draft is still pending the file is ADOPTED onto it (the result says duplicateAttachment:'added') and no second draft is created; the same repair works on import_bank_statement with the identical account, balances and rows. The link is single-use, expires quickly, and works only for this company. Use this for anything bigger than a few KB; keep attachmentBase64 for tiny files only.

ParametersJSON Schema
NameRequiredDescriptionDefault
filenameNoOptional original filename, e.g. receipt.jpg — travels with the upload and shows on the review card.
mediaTypeNoOptional hint of the file's MIME type, e.g. 'image/jpeg'. Advisory only — the server determines the real type from the file's own bytes (magic bytes), so a wrong hint changes nothing.

TDQS

A4.7/5.0
Behavior5/5

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

The annotations give little behavioral detail, so the description carries the full burden, and it does so thoroughly. It discloses that the link is single-use, expires quickly, is company-specific, that the server determines MIME type from raw bytes, and that the token can be adopted onto an already-pending draft, including the duplicateAttachment result.

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

Conciseness5/5

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

Although long, the description is dense with non-redundant, decision-relevant information: purpose, usage order, repair workflow, and constraints. It is front-loaded with the core purpose and each subsequent sentence addresses a likely agent question or failure mode.

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 there is no output schema, the description compensates by explicitly naming the return values (uploadUrl, attachmentToken) and explaining how they are used. It covers the complete workflow across all sibling create tools, the bank import path, and the re-file repair scenario, leaving no significant gap for an agent.

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 fully documents filename and mediaType, including the advisory nature of mediaType. The tool description adds no new parameter-specific meaning beyond what the schema provides, so the baseline of 3 is appropriate.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Get a one-time link to upload' a document, and clarifies the exact use case (large files too costly to inline as attachmentBase64). It clearly distinguishes itself from sibling create/import tools and from get_attachment by focusing on the upload-link step.

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 provides explicit when-to-use guidance ('Use this for anything bigger than a few KB; keep attachmentBase64 for tiny files only') and when-to-call ordering ('CALL THIS FIRST, BEFORE the create/import call'). It names the alternative (inline attachmentBase64) and even includes a detailed repair path if the create call was already made without the token.

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

resolve_customerFind customerA
Read-only
Inspect

Resolve a customer name for an invoice draft against this company's real customers. Statuses: resolved (with id + current outstanding A/R balance — the credit-check-in-chat moment), ambiguous (with candidates), or none. When there is no exact/prefix match but existing customers look CLOSE (nearMiss:true), the name is likely salesperson shorthand for one of them ("JJ Dungun" for "PERNIAGAAN JJ") — ask the user which one; only file as new if they confirm it is genuinely new. Never guess among candidates — ask the user.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnlyHint=true and openWorldHint=false; the description adds far richer behavior: the three-status result model, the nearMiss flag with a concrete example ('JJ Dungun' for 'PERNIAGAAN JJ'), what data comes back in the resolved case, and the hard constraint to ask rather than guess. Nothing contradicts the read-only annotation — resolving is consistent with not mutating state.

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 sentences: purpose, status model, and the nearMiss/ask-user rule. Each adds distinct value and the purpose is front-loaded, but the closing 'Never guess among candidates — ask the user' mildly restates the earlier ask-the-user instruction, so one clause is slightly redundant.

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 minimal schema (1 param, no output schema) with nuanced behavior, the description is near-complete: it covers every outcome the agent will face, what data comes back in the resolved case (id + A/R balance), how to recognize shorthand matches, and what to do in each branch. The only minor omission is an explicit next-step for the 'none' status, but the confirm-before-creating rule effectively covers 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 0% with only a bare 'name' string field, so the description must compensate. It does: the first sentence establishes that the parameter is a customer name as written on an invoice draft, and the nearMiss discussion clarifies fuzzy and prefix-matching semantics. Only a formal 'name: ...' parameter breakdown is missing, which matters little for a single obvious 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?

The description opens with a specific verb and resource: 'Resolve a customer name for an invoice draft against this company's real customers.' It enumerates three distinct outcomes (resolved, ambiguous, none) with their payloads, and the customer-specific scope clearly distinguishes it from sibling tools resolve_vendor and resolve_product.

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 strong decision rules: report nearMiss matches as likely shorthand and ask the user, only file as new on explicit confirmation, and never guess among candidates. It does not explicitly name alternatives (e.g., use resolve_vendor for vendors), but the customer-scoped framing and the detailed handling rules make when-to-use clear. An explicit when-not-to-use note would fully close the gap.

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

resolve_productFind productA
Read-only
Inspect

Resolve a product by name or SKU for an invoice line. Returns id, sku, name, unit and the default sell price the form would use. Plain names or SKUs work best. Statuses: resolved / ambiguous (candidates) / none — never guess among candidates.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes

TDQS

A4.8/5.0
Behavior5/5

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

The description discloses return fields (id, sku, name, unit, default sell price), statuses (resolved/ambiguous/none), and the critical rule 'never guess among candidates.' This goes well beyond the readOnlyHint annotation by explaining how ambiguity is handled.

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

Conciseness5/5

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

The description is three sentences with no fluff: purpose, return values, and behavior. It is front-loaded with the core action and immediately useful details.

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 simple lookup tool with one parameter and no output schema, the description is complete. It specifies input semantics, output fields, statuses, and a safety rule against guessing, making the tool's behavior fully transparent.

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?

With 0% schema description coverage, the description fully compensates by explaining that 'query' accepts a product name or SKU, and that plain forms work best. This gives the agent the semantic meaning needed to invoke the tool correctly.

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

Purpose5/5

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

The description clearly states 'Resolve a product by name or SKU for an invoice line,' using a specific verb and resource. It distinguishes from sibling tools like resolve_customer and resolve_vendor by explicitly targeting products.

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 phrase 'for an invoice line' provides clear usage context, and 'Plain names or SKUs work best' offers practical input guidance. However, it does not explicitly name alternatives or state when not to use this tool, so it falls 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.

resolve_vendorFind vendorA
Read-only
Inspect

Resolve a supplier / vendor name for a bill draft against this company's real vendors. Statuses: resolved (with id), ambiguous (with candidates), or none. When there is no exact/prefix match but existing vendors look CLOSE (nearMiss:true), the name is likely shorthand for one of them — ask the user which one; only file as new if they confirm it is genuinely new. Never guess among candidates — ask the user.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

TDQS

A4.3/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses matching behavior (exact/prefix vs nearMiss) and the required user-confirmation workflow ('only file as new if they confirm', 'ask the user'). This prevents an agent from auto-resolving or auto-creating records. It does not contradict the read-only annotation because 'file as new' is framed as a downstream decision, not a write performed by this tool.

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

Conciseness5/5

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

Three sentences: first sets purpose and possible statuses, second details the nearMiss rule including the confirmation requirement, third is a clear imperative ('Never guess among candidates'). Information is front-loaded and no sentence is filler.

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 one-parameter, no-output-schema tool with readOnlyHint=true, the description covers the call's purpose, parameter, returned status categories (resolved/ambiguous/none with id/candidates), and disambiguation behavior. The only minor gap is an explicit action for the 'none' status, but the overall guidance is sufficient 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?

With 0% schema coverage, the description compensates by identifying the sole parameter as a 'supplier / vendor name' for a bill draft and clarifying how it is matched (exact/prefix, nearMiss). It adds semantic context beyond the raw string field. It doesn't specify formatting or case rules, but for a single string this is sufficient.

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 'Resolve a supplier / vendor name for a bill draft against this company's real vendors' – a specific verb, object, and target dataset. It also lists the three outcome statuses, making the operation's scope concrete. It doesn't explicitly contrast with resolve_customer/resolve_product, but the vendor-specific wording is enough to identify the intended tool.

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

Usage Guidelines4/5

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

Gives clear context: the tool is for bill-draft vendor names matched against real vendors, and instructs to 'ask the user' whenever candidates are ambiguous or nearMiss. It explicitly says 'Never guess among candidates,' which is a strong usage rule. It doesn't name alternative sibling tools for exclusion, so no direct when-not-to-use statement.

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

revise_draftRevise a pending draftAInspect

Correct a draft you already filed, instead of filing it again. Pass the draft's kind and id plus a patch of just the fields that were wrong — the server re-validates them exactly as it did at filing (same account rules, same date rules, same line derivation, same totals) and updates the draft in place. Use this whenever you realise a filed draft is wrong: for an expense, re-calling create_expense_draft with corrected fields is refused as a duplicate of the very draft you are trying to fix, and for every kind a second create files a CONFUSING SECOND DRAFT the human then has to notice and reject — revise the one you filed instead. ONLY a PENDING draft can be revised; a draft the user has already approved or rejected (or one that has expired) is refused, naming its status — file a fresh draft in that case. Fields you do not send are left exactly as filed. REVISING DOES NOT APPROVE ANYTHING: the draft stays pending, nothing posts, and the human still taps Approve in Taokeh — the same one-tap link from the original filing still works and shows the revised figures. The reviewer is TOLD it changed: a short 'revised by your AI' line naming the changed fields is appended to the note they read on the approval card, so add a plain-language note saying WHY you revised it.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYesWhich kind of draft to amend — the same ten kinds the create_*_draft tools file. 'sales_debit_note' is the SELL-side debit note create_debit_note_draft files (an additional charge on an invoice you issued); 'journal' is the adjusting entry create_journal_draft files.
noteNoA SHORT plain-language reason for the revision, in the reviewer's language — 'the paid-from account should be the owner's capital account, not petty cash'. It is APPENDED to the note they already have (nothing is overwritten) and shows on the approval card. Keep it to a sentence.
patchYesOnly the fields you are correcting. Every key must belong to this draft kind — a misspelled or foreign key is refused rather than silently ignored. The card IMAGE of a contact draft and the original document riding any other draft are deliberately NOT patchable: they are the evidence the approver checks your fields against.
draftIdYesThe draftId the create_*_draft call returned.

TDQS

A4/5.0
Behavior5/5

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

The description details side effects: it updates in place, re-validates, appends a note to the approval card, and does not approve the draft. It also clarifies that the reviewer is told about the change and that the original document/image is not patchable. This goes well beyond the minimal annotations.

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

Conciseness4/5

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

The description is front-loaded with the main purpose and then provides detailed behavioral notes. It is somewhat verbose with repetitive emphasis (e.g., 'Fields you do not send...' and 'REVISING DOES NOT APPROVE ANYTHING'), but the structure is logical and information is well-organized.

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

Completeness3/5

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

The description thoroughly covers behavior, constraints, and side effects, but does not mention what the tool returns or the expected response format. Since there is no output schema, this is a notable absence. It also doesn't address errors or edge cases beyond refusing foreign keys, but that may be acceptable.

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?

The schema already provides 100% description coverage for every parameter, so the baseline is 3. The tool description adds some high-level guidance, such as 'patch of just the fields that were wrong' and 'every key must belong to this draft kind', but these largely restate schema details. No significant new parameter meaning is added.

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

Purpose4/5

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

The description opens with 'Correct a draft you already filed, instead of filing it again', clearly stating the action and target. It distinguishes from create_*_draft by explaining why re-calling create is refused, but it does not mention the update_*_draft sibling tools, leaving some ambiguity about tool selection.

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

Usage Guidelines4/5

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

The description explicitly says 'Use this whenever you realise a filed draft is wrong' and explains 'instead of filing it again', giving a clear condition. It also states that only a PENDING draft can be revised, which is an important constraint. However, it does not discuss the update_*_draft alternatives, so guidance is not fully exhaustive.

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

sales_summarySales summaryA
Read-only
Inspect

How much you have sold. With no dates: today and this month so far. With a date range: the invoiced sales for that period, broken down by month, customer and product.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
fromNo

TDQS

A4.4/5.0
Behavior4/5

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

The description adds behavioral context beyond the readOnlyHint annotation by explaining how the absence or presence of date parameters changes the output, and by specifying the grouping dimensions. It does not describe return structure, but it provides meaningful behavioral detail.

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

Conciseness5/5

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

Two concise, front-loaded sentences. The first states the purpose, the second explains parameter behavior and output breakdown. Every word earns its place with no 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?

Given the tool has no output schema and only two optional parameters, the description covers the essential behavior: what is returned and how date ranges affect it. It could specify whether the breakdown is separate or combined, but for a summary tool this is sufficiently 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 0% (no descriptions for 'from' and 'to'), so the description must compensate. It does so by explaining the effect of date ranges vs. no dates. It implicitly maps the parameters to the range, giving them semantic meaning beyond the schema's basic format.

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

Purpose5/5

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

The description clearly states 'How much you have sold' and specifies it covers invoiced sales, distinguishing it from other financial reports. It also mentions the breakdown dimensions (month, customer, product), making its purpose specific and unambiguous.

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 clear guidance on usage: with no dates it shows today and this month, with a date range it shows the period's sales. It does not explicitly mention alternatives or when not to use, but the context is sufficient for selecting the tool.

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

search_document_linesSearch document linesA
Read-only
Inspect

Read the LINE ITEMS of posted documents IN BULK — what was actually sold or bought, line by line, across many documents in one call. search_documents answers WHICH documents; this answers WHAT WAS ON THEM. Use it for any question that needs the detail behind the totals: average price per item across a year, how a price moved between two customers, which sizes or grades actually shift, how much of something was supplied. Without it the only way to see lines was to open one PDF per document — 180 documents is 180 round trips and 180 chances to misread a layout. docType is REQUIRED and must be one of: 'invoice', 'credit_note', 'sales_debit_note' (an additional charge this business issued to a customer), 'bill', 'debit_note' (the BUY-side one, raised against a supplier). Narrow with any combination of number (partial doc number — on invoices this also matches the customer's own Ref No, their DO/PO number), party (partial customer or vendor name), from/to (document date range) and productText — a case-insensitive contains matched against the PRODUCT NAME or the LINE DESCRIPTION, so "chengal" or "2x4" pulls only those lines. docType on its own is a legitimate whole-book pull. Each row: docId, docNumber, docDate, party, lineNo, product {sku, name}, description, quantity, unit, unitPrice, unitCost, discount, lineTotal, taxCode — verbatim from what was posted, never re-derived. ⚠ DIMENSIONS AND SPECIFICATIONS ARE TEXT, NOT FIELDS. Taokeh has no column for a timber size, a grade, a colour or a variant: they live inside the product name and the line description as the business types them ("Chengal 2x4x8"). So this hands you that text as written and YOU do the parsing and the grouping — the server will not invent a dimension it does not store, and two lines for the same real size may be spelled differently. unit is the unit of measure stamped on the line when it was posted (falling back to the product's current unit on lines posted before that was stored) — a measured trade line may be in tons or feet, so never assume pieces. Rows come back newest document first, then in the document's own line order, capped at 200 with total, shown and more — when more is true, narrow by date (from/to) and pull the periods in turn rather than accepting a partial answer as the whole. unitCost is the COST BASIS STAMPED ON THE LINE WHEN IT WAS POSTED — like unit and the tax code beside it — so a historical line reports the cost as of THAT SALE, not the product's cost today. That is what makes per-product margin answerable here: unitPrice − unitCost, line by line. On a BILL or a buy-side debit note there is only one price column, so unitCost and unitPrice are the same figure — what the SUPPLIER charged. ⛔ WHAT IT WILL NOT DO: it covers posted documents only — quotes, delivery orders and purchase orders are not here, because Taokeh does not store the unit of measure on their lines and reporting a guessed unit would be worse than refusing. Header-only search: search_documents. Paid expenses (which have no product lines): search_expenses. The ledger postings behind a document: search_journal. Nothing is written, and no draft is created.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest DOCUMENT date (YYYY-MM-DD).
refNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
skuNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
fromNoEarliest DOCUMENT date (YYYY-MM-DD). The main way to break a >200-line pull into honest slices.
itemNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
sizeNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them). There is no size field to filter on.
textNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
docIdNoNOT a filter on this tool. This tool reads lines across MANY documents — narrow by `number` (the document number), `party` or a date range instead. For one document, pass its number as `number`.
limitNoNOT a filter on this tool. The page size is fixed at 200 lines. Narrow with from/to, party or productText and pull the periods in turn.
partyNoPartial customer or vendor name (case-insensitive contains).
refNoNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
numberNoPartial doc number (case-insensitive). On INVOICES this also matches the customer's own Ref No — their DO or PO number.
vendorNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docTypeNoREQUIRED. One of: 'invoice', 'credit_note', 'sales_debit_note', 'bill', 'debit_note'. Note the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer; 'debit_note' is the BUY side, against a supplier bill.
productNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
customerNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
supplierNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docNumberNoNOT a filter on this tool. Pass the document number as `number` (partial matches are fine).
productIdNoNOT a filter on this tool. This search matches product TEXT, not ids — pass the name or size words as `productText`.
referenceNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
descriptionNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
productNameNoNOT a filter on this tool. Pass it as `productText` — one case-insensitive contains matched against BOTH the product name and the line description, which is where sizes, grades and variants live (Taokeh stores no column for them).
productTextNoCase-insensitive text matched against the PRODUCT NAME or the LINE DESCRIPTION — this is where sizes, grades and variants live, because Taokeh stores no column for them. e.g. "chengal", "2x4".

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only provide readOnlyHint and openWorldHint; the description adds substantially more behavior: the 200-row cap with `total`/`shown`/`more` and the slicing strategy, row ordering ('newest document first, then in the document's own line order'), the verbatim-never-re-derived guarantee, `unitCost` as cost-at-posting-time, unit fallback behavior, and 'Nothing is written, and no draft is created.' These claims align with the annotations rather than contradicting them.

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 (~450 words) but deliberately structured: purpose first, then usage motivating examples, then gotchas with visual markers (⚠, ⛔). Some redundancy exists — the 'dimensions and specifications are text' caveat is restated several times, and the 180-PDF round-trip motivation is optional — but each major section carries unique information an agent needs.

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 explaining return values, and it does: it enumerates every row field (docId, docNumber, docDate, party, lineNo, product {sku, name}, description, quantity, unit, unitPrice, unitCost, discount, lineTotal, taxCode), states ordering, documents the 200-cap with `total`/`shown`/`more`, and pre-empts semantic traps (units not pieces, buy-side unitPrice=unitCost, dimensions as free text). For a 23-parameter tool this is complete.

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%, but the description adds meaning well beyond the field comments: docType is called out as REQUIRED with the buy-side vs sell-side debit-note distinction, `number` is clarified as also matching the customer's Ref No/DO/PO, and `productText` is explained as matching BOTH product name and line description with concrete examples ('chengal', '2x4'). It explains the domain reason behind the matching behavior — Taokeh stores no dimension column — which 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?

The opening sentence states a precise verb+resource: 'Read the LINE ITEMS of posted documents IN BULK — what was actually sold or bought, line by line, across many documents in one call.' It explicitly differentiates from the closest sibling: 'search_documents answers WHICH documents; this answers WHAT WAS ON THEM.' There is no ambiguity about what this tool does.

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

Usage Guidelines5/5

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

Gives concrete when-to-use scenarios ('average price per item across a year, how a price moved between two customers, which sizes or grades actually shift'), names the exact alternatives ('Header-only search: search_documents. Paid expenses: search_expenses. The ledger postings behind a document: search_journal'), and states explicit exclusions ('quotes, delivery orders and purchase orders are not here'). Nothing is left to inference.

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

search_documentsSearch documentsA
Read-only
Inspect

Find invoices, credit notes, sell-side debit notes, quotes, delivery orders, bills, buy-side debit notes and purchase orders by any combination of: doc number (partial), party (customer/vendor) name (partial), date range, amount range, due-date window (invoices and bills), and doc type. Returns compact rows (docId, type, number, date, party, total, status), newest first, capped — with a more flag when there are further matches to narrow down. INVOICE rows carry two more fields: refNo, the CUSTOMER's own reference for that job — their delivery-order or purchase-order number, the one they quote back at you on the phone — and dueDate, the date that invoice falls due. refNo is NOT the invoice number; the invoice's own number is number. refNo is null when the invoice was raised without one. dueDate is null on a CASH sale — paid at the counter, so it is not money anyone is waiting on and it deliberately sits outside every due-date window and aging bucket; a null there means CASH, not a missing date. Only CREDIT invoices report one. BILL rows carry dueDate too — the date a supplier bill falls due, from the payment term printed on it, and null on a CASH bill for the same reason. Only invoices carry refNo (a bill's own number IS the supplier's number, so it needs no second field), and only invoices and bills carry dueDate — every other type omits them rather than reporting null about a column its document has no such thing as. number searches BOTH, so "find INV-0031" and "find the invoice for their DO 1074" are the same call. Invoices, credit notes, bills and quotes also report whether their ORIGINAL document (a scan or upload) is on file: hasAttachment plus an attachments list you can fetch with get_attachment. Delivery orders and purchase orders omit that field because they cannot carry an original. INVOICES, CREDIT NOTES and SELL-SIDE DEBIT NOTES (sales_debit_note — additional charges this business added to an invoice it issued; not to be confused with debit_note, the buy-side one raised against a supplier bill) also carry an einvoice field — this business's MyInvois posture for that document AS RECORDED IN TAOKEH: validated (a MyInvois validation is recorded here, with uuid + validatedAt), consolidated (covered by a consolidated e-invoice, which holds the uuid — the individual document has none by design), platform (a marketplace sale: Shopee/TikTok Shop/Lazada issues the e-invoice, nothing for this business to submit), exported (put into a MyInvois batch export from Taokeh, nothing recorded back yet) or none. Taokeh CANNOT see the MyInvois portal, so say "no validation recorded in Taokeh" — never "never submitted to LHDN". Bills and buy-side debit notes omit the field. Use the docId with get_attachment (the SOURCE document someone filed) or get_document_pdf (the PDF Taokeh generates). PAYMENTS — docType:'payment' — are an OPT-IN type you must ask for BY NAME: they are never included when you omit docType, because a payment is not a document. It is a BANK LINE that invoices or bills point at, so the grain is the movement of money: one receipt that settles three invoices is ONE row carrying three allocations ({docId, docType, docNumber, party, amount, amountForeign, notes}). An allocation's docType is the real kind of the document settled — 'invoice', 'credit_note' (a refund walks a credit note back), 'sales_debit_note', 'bill' or 'debit_note' — not an assumption from which side of the books it sits on, and notes is that allocation's own note rather than one note borrowed for the whole transfer. That makes "which payment covered INV-0031" a single call — number and party here match the ALLOCATED documents, not the bank line, and on the invoice side number also matches the customer's own Ref No (their DO/PO number, or a marketplace order key), exactly as it does for invoices in the ordinary search. Each row: docId (⚠ a BANK TRANSACTION id, NOT a document id — do not hand it to get_document_pdf or get_attachment), date, direction ('in'/'out'), total (the bank line's own magnitude), status (the bank row's status), bankAccount, party (the single customer or supplier when every allocation is to the same one, else null — read the per-allocation party then), source and description (the bank line as stored). source is DERIVED from where the line came from, not stored: 'statement' (it arrived on an imported bank statement and a human matched it in Banking), 'receipt_draft' or 'payment_draft' (an AI-filed draft the owner approved), or 'manual' — recorded by hand in the app, which is EVERYTHING ELSE rather than one door: the receipt door, the /go command bar, the supplier-payment door, a refund against a hand-recorded line. Taokeh does not distinguish them, so do not tell the owner which screen was used. A NEGATIVE allocation amount is a REFUND walking that document back down, not a settlement. CONTRAS ARE NOT PAYMENTS and never appear here: a set-off moves no bank money, and Taokeh books it as two internal clearing lines which are excluded from this read on purpose. To see one, use search_journal or the contra note on the documents themselves.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
refNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
fromNo
textNoNOT a filter on this tool. This search matches document numbers and party names only — use `number` or `party`. To search memo/line text, use search_journal (`text`) or search_expenses (`text`).
dueToNoLatest DUE date (YYYY-MM-DD). Same docType rule as dueFrom — 'invoice' or 'bill'. Pair the two for a window: dueFrom + dueTo across this week with docType:'bill' answers "what do I owe before Friday"; dueTo alone with a past date is everything already due.
partyNoPartial customer or vendor name (case-insensitive contains).
refNoNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.
numberNoPartial doc number / reference (case-insensitive). On INVOICES this also matches the customer's own Ref No — their DO or PO number, whatever they printed on the paperwork. So a customer chasing "our PO 4471" is one call: pass 4471 here. That Ref No is NOT the invoice number; the invoice's own number matches here too, and you cannot tell from a hit which of the two it was — read `number` and `refNo` on the row it comes back with. On MARKETPLACE-IMPORTED invoices the Ref No is the platform's order key (SHOPEE-<order_sn>, TIKTOK-<order id>, SHOPIFY-<order id>), not a customer's number — so a marketplace order id pasted here finds its invoice too.
vendorNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docTypeNoRestrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order','payment'. Omit for all — EXCEPT 'payment', which is opt-in only and is never returned unless you name it. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill.
dueFromNoEarliest DUE date (YYYY-MM-DD) — this is the "what's due this week" filter, and it asks about when the money falls due, not when the document was raised (that's `from`/`to`). INVOICES OR BILLS, one at a time: pass docType:'invoice' (money coming in) or docType:'bill' (money going out) with it, or the call is refused. Nothing else in this search has a due date, and quietly dropping every quote and delivery order would be a wrong answer wearing a right one's clothes; netting receivables and payables into one list would be another.
customerNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
supplierNoNOT a filter on this tool. Pass a customer or vendor name as `party`.
docNumberNoNOT a filter on this tool. Pass the document number as `number` (partial matches are fine).
maxAmountNo
minAmountNo
referenceNoNOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`.

TDQS

A4.9/5.0
Behavior5/5

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

Despite readOnlyHint=true already covering safety, the description adds extensive behavioral context: payment docId is a bank transaction id (not a document id), refNo is not the invoice number, null dueDate means cash not missing data, einvoice status is 'as recorded in Taokeh' (not portal truth), source is derived not stored, and contras are intentionally absent. This goes far beyond what annotations could convey.

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

Conciseness4/5

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

The description is front-loaded with the core purpose and results, and every sentence carries real semantic weight. However, it is a very long single block with some repetition (the customer Ref No / DO-PO concept is restated multiple times in the description and schema), so it sacrifices scanability for completeness.

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 specifies return-row semantics: which fields appear on which doc types, field omissions vs nulls, payment allocations grain, capped results with more flag, and special id warnings. An agent has everything needed to call correctly and interpret results without guessing.

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 76%, but the description substantially enriches parameter meaning: number searches both document number and customer Ref No, dueFrom/dueTo are due-date (not document-date) filters restricted to invoice/bill, docType disambiguates sales_debit_note vs debit_note, and multiple 'NOT a filter' params are correctly routed to canonical parameters. It more than compensates for the remaining undocumented params.

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 ('Find') and enumerates exact document types and filter combinations, immediately distinguishing it from line-level, journal, and expense searches. The return row description clarifies what a search_documents hit looks like, and the payments section further scopes the tool to document-grain and bank-line 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?

Explicitly names alternatives: search_journal for contras/text, search_expenses for text, get_attachment/get_document_pdf for fetching artifacts, and states payments are opt-in by name. It also gives when-not-to-use cases (dueDate filters only with invoice/bill; contras excluded) and reasons for the exclusions.

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

search_expensesSearch paid expensesA
Read-only
Inspect

Search PAID EXPENSES already posted to the books (the /expenses ledger) by any combination of: reference (partial), text in the memo/description (partial), date range, amount range, and category account. Returns compact rows (expenseId, date, amount, category account code + name, memo, reference), newest first, capped — with a more flag. Every row also says whether the ORIGINAL RECEIPT is on file: hasAttachment plus an attachments list (filename, media type, size) — an empty list means genuinely no receipt is attached, not "unknown". To read one, pass the row's expenseId and attachmentId to get_attachment. ALWAYS check here BEFORE filing an expense draft (create_expense_draft): if the same receipt is already booked, filing again would double-book it. search_documents does NOT cover paid expenses — this tool is the only way to see them.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
refNoNOT a filter on this tool. Pass the supplier/receipt reference as `reference`.
fromNo
memoNoNOT a filter on this tool. Pass memo text as `text`.
textNoPartial text to match in the expense memo/description (case-insensitive contains).
refNoNoNOT a filter on this tool. Pass the supplier/receipt reference as `reference`.
numberNoNOT a filter on this tool. Pass the supplier/receipt reference as `reference` — a posted expense has no document number of its own.
vendorNoNOT a filter on this tool. A posted expense carries no party field here — search the supplier name as `text` (it matches the memo/description) or as `reference`.
accountNoNOT a filter on this tool. Pass the chart-of-accounts code as `accountCode` (exact).
categoryNoNOT a filter on this tool. Pass the category by its chart-of-accounts code as `accountCode` (exact) — get codes from expense_accounts.
supplierNoNOT a filter on this tool. A posted expense carries no party field here — search the supplier name as `text` (it matches the memo/description) or as `reference`.
maxAmountNo
minAmountNo
referenceNoPartial supplier/receipt reference (case-insensitive contains).
accountCodeNoRestrict to one expense category by its account code (exact).
descriptionNoNOT a filter on this tool. Pass memo text as `text`.

TDQS

A4.7/5.0
Behavior5/5

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

The description adds substantial behavioral detail beyond the readOnlyHint annotation: returns are capped with a 'more' flag, rows are newest first, attachment semantics are clarified ('an empty list means genuinely no receipt is attached, not "unknown"'), and it explains how to read an attachment via get_attachment. This is rich context an agent cannot infer from the schema alone.

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 dense but every sentence earns its place: scoping, filter semantics, return shape, attachment behavior, linking to get_attachment, and usage guidance are all present. It is front-loaded with the core purpose, though the single-paragraph format makes it slightly less scannable than it could be.

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 16 parameters, sparse annotations, and no output schema, the description does a strong job of covering return rows, attachment semantics, the recurrence of the double-booking risk, and the relationship to get_attachment. Minor gaps remain: it discloses that results are 'capped' with a 'more' flag but does not explain how the agent would retrieve the next page, and it leaves pagination behavior partially implicit.

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

Parameters4/5

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

The description communicates the intended filter combination: 'by any combination of: reference (partial), text in the memo/description (partial), date range, amount range, and category account.' It also, through the many 'NOT a filter' schema descriptions and the phrase 'Pass memo text as text', actively steers the agent away from plausible but wrong parameters. It does not enumerate every accepted parameter, but the schema already documents most of them well.

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: 'Search PAID EXPENSES already posted to the books' and goes on to list the exact filter dimensions. It also differentiates itself from sibling tools by noting that 'search_documents does NOT cover paid expenses — this tool is the only way to see them.'

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 when-to-use guidance: 'ALWAYS check here BEFORE filing an expense draft (create_expense_draft): if the same receipt is already booked, filing again would double-book it.' It also names the alternative it is not and states this tool is the only way to see paid expenses.

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

search_journalSearch journal entriesA
Read-only
Inspect

Search the general ledger's JOURNAL ENTRIES — every posting, whatever door created it (a manual journal, a scanned receipt, an invoice, a bank row, a paid expense, payroll, depreciation…). Returns each entry WITH its balanced lines (account code + name, debit, credit, line description), so you can see exactly HOW something was booked, not just that it exists. Filter by any combination of: date range, text (case-insensitive, matched against the entry memo AND its line descriptions), accountCode (entries touching that account), source (the door that created it), and an amount range on the entry's total debits. Give at least one filter — this never dumps the whole ledger. Newest first, capped, with a more flag. Pairs with search_expenses for reconciling: search_expenses shows what the /expenses register holds, search_journal shows every ledger entry including journal-era postings the register never covered. Read-only — it changes nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNo
refNoNOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`.
fromNo
memoNoNOT a filter on this tool. Pass memo text as `text` (it matches the entry memo AND every line description).
textNoPartial text matched against the entry memo AND its line descriptions (case-insensitive contains).
partyNoNOT a filter on this tool. The ledger has no party column — search the name as `text`, or find the document with search_documents.
refNoNoNOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`.
numberNoNOT a filter on this tool. A journal entry has no document number — search its memo and line descriptions with `text`, or find the document itself with search_documents.
sourceNoThe door that created the entry (exact, case-insensitive). One of: MANUAL, SALE, PURCHASE, ADJUSTMENT, BANK, CREDIT_NOTE, DEBIT_NOTE, PAYROLL, IMPORTED_SERVICE, FX_REVAL, DEPRECIATION, ASSET_DISPOSAL, EXPENSE, LOAN, REVENUE_RECOGNITION, ASSET_ACQUISITION, BANK_OPENING. Omit for all.
accountNoNOT a filter on this tool. Pass the chart-of-accounts code as `accountCode` (exact).
maxAmountNoMaximum entry size, measured on the entry's total debits (MYR).
minAmountNoMinimum entry size, measured on the entry's total debits (MYR).
referenceNoNOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`.
accountCodeNoRestrict to entries that have a line on this account code (exact).
descriptionNoNOT a filter on this tool. Pass the text as `text` (it matches the entry memo AND every line description).

TDQS

A4.7/5.0
Behavior5/5

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

The description aligns with annotations (readOnlyHint=true, 'Read-only — it changes nothing') and adds substantial behavioral detail beyond them: it explains the return format (lines with account code/name, debit, credit, description), that it returns newest first with a cap and a `more` flag, and that it never returns the whole ledger without filters. This fully discloses the key behaviors.

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

Conciseness5/5

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

The description is detailed but every sentence earns its place: it opens with the purpose, then the return value, then filters, then the filter requirement, then order/cap/more, then the pairing, then read-only. It is well-structured, front-loaded, and avoids redundancy with the schema (e.g., it does not repeat the source enum list).

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

Completeness5/5

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

Given the tool's complexity (15 parameters, no output schema), the description covers all essential aspects: what it searches, what it returns, how to filter, the caution against dumping the whole ledger, ordering, pagination via `more`, and its relationship to sibling tools. It also leverages the schema's 'NOT a filter' hints to prevent misuse. Nothing critical is missing.

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

Parameters3/5

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

Schema coverage is 87%, so the schema already documents most parameters. The description adds a summary of filter categories (date, text, accountCode, source, amount) and clarifies that `text` matches memo AND line descriptions—but the schema already states this. It confirms how amount range is measured (total debits), but again that is in the schema. The description does not significantly augment the schema beyond an organizational overview, so a baseline of 3 is appropriate.

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

Purpose5/5

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

The description states a specific verb ('Search') and a precise resource ('the general ledger's JOURNAL ENTRIES') and clearly distinguishes it from siblings by contrasting with search_expenses and search_documents. It also explains the return of balanced lines, so an agent can tell exactly what this tool does relative to others.

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 states when to use ('Pairs with search_expenses for reconciling') and when not to ('This never dumps the whole ledger' implies filters required). It also lists concrete filter combinations and provides alternatives via 'NOT a filter' parameter hints, which guide the agent to `text` or `accountCode` instead. This gives clear context but could have stated explicit exclusions more directly.

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

shoebox_itemsShoebox items waitingA
Read-only
Inspect

List the photos sitting in this company's SHOEBOX — paper the people in the business snapped on their phones and sent in, which NOBODY has read yet. This is the pile to work from when the user asks you to "do the receipts" or "clear the shoebox". Only items still waiting are listed: anything already booked or set aside is settled and deliberately absent. For each item you get its id, what kind of paper it is, the file name, type and size, when it arrived (Malaysia time) and who sent it in — never an amount, because nothing has been read. To SEE one, call get_attachment with owner:'shoebox' and the item's id; you read the photo yourself, on your own subscription — Taokeh does not OCR or interpret it for you. To BOOK one, file the matching draft (create_expense_draft, create_bill_draft or create_invoice_draft) with shoeboxItemId set to that id, and DO NOT re-send the photo: the server attaches its own stored copy, so it rides the draft and lands on the posted document on approval. An item already carrying a pending draft says so (pendingDraft) — file nothing more against it; correct the existing draft with revise_draft instead. An item TAOKEH itself is already reading says so too (beingRead): someone tapped "Book it" or asked Taokeh to book the shoebox, that read is paid for and its draft is waiting for the owner at the reviewPath given — file nothing against it either, and tell the user where it is waiting. Reading this pile costs the company no AI credits.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoHow many waiting items to return, newest first. Defaults to 50.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations declare readOnlyHint=true and the description reinforces a safe, read-only profile, adding a cost disclosure ('Reading this pile costs the company no AI credits'). It transparently discloses return-field semantics — explicitly 'never an amount' — plus the fact that Taokeh does not OCR/interpret photos and the agent must read them itself on its own subscription. The material is rich, though the corrupted run-on in the middle makes some disclosures harder to parse.

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?

The description is far longer than necessary for a one-parameter list tool, and the middle section is visibly corrupted — repeated phrases, missing punctuation, and a broken 'two-send the photo' fragment. Purpose and cost notes are nicely front-loaded, but the excessive, garbled prose fails the conciseness test.

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

Completeness4/5

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

For a tool with one optional parameter and no output schema, the description covers the essential operational facts: exact fields returned, how to view an item, how to book it, and which state flags (pendingDraft, beingRead) to respect before acting. Nothing an agent needs to invoke it correctly is missing; the garbled prose hurts readability but not coverage.

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%: the single optional `limit` parameter is fully documented with default (50), maximum (200), and ordering ('newest first'). The tool description adds nothing about `limit`, so the baseline of 3 applies — the schema carries the load.

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 — 'List the photos sitting in this company's SHOEBOX' — and sharply scopes it to items nobody has read yet. It differentiates from siblings by naming the viewing tool (get_attachment) and booking tools (create_*_draft), so an agent knows this is the unread-inbox list, not the action tool. The garbled middle section does not obscure this core purpose.

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 trigger phrases: 'the pile to work from when the user asks you to do the receipts or clear the shoebox'. Routes next steps to named alternatives (get_attachment to view, specific create_*_draft tools to book) and states exclusion rules (don't file against items with pendingDraft or beingRead). This is about as explicit as usage guidance gets.

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

stage_documentStage a historical documentAInspect

Bring ONE already-issued historical document (a sales invoice, or a supplier bill) across from the system this company is migrating FROM. This is the BULK migration door and it is NOT create_invoice_draft: nothing is posted, nothing is drafted for individual approval, and no approval card is raised per document. Staged documents group into monthly batches the owner reviews and approves together at /switch/documents. Use it ONLY for documents that were genuinely issued in the old system (or written in a paper book) — a NEW document belongs in create_invoice_draft / create_bill_draft. The lane must be OPEN (the owner turns it on at /switch → "Bring over your documents") and it can only be open before the books are locked; if it is closed the call is refused with instructions. IDEMPOTENCY IS ON sourceDocId: staging the same sourceDocId again UPDATES that pending row instead of filing a second one. Once the owner has ENTERED it, or deliberately LEFT IT OUT, nothing you send can change it, re-book it or bring it back — only the owner can. So re-running your whole export is always safe. THE CUTOVER: bring over only documents dated AFTER the company's accounting start date. Anything dated on or before it is already carried by the owner's opening balances, and Taokeh will flag it and refuse to enter it — staging those wastes both our time, so filter them out of your export if you can. ORDER MATTERS: stage the SUPPLIER BILLS for a period before the sales invoices for it, because Taokeh works out cost of sales from the stock that was bought. The server re-computes every quantity and the grand total from the lines (with SST); your own printed total goes in sourceTotal and is used ONLY to show the owner a tie against the server's figure. Anything the server cannot settle — a product that does not resolve, a customer name matching several contacts, a printed total that disagrees — is staged anyway, FLAGGED, and held out of bulk approve for the owner to open individually. The document keeps its ORIGINAL number (reference) and its ORIGINAL date, and posts marked as historical so Taokeh never e-invoices or chases it. PAPER: if you read this document off a photo or a scan, ATTACH IT — request_attachment_upload, PUT the bytes, pass attachmentToken here. The owner then reviews your figures beside the actual slip on that document's own screen, edits anything you misread, and approves it there; the original lands on the posted document. Without it they are approving your arithmetic on your word alone. Show your per-line working, and mark any balancing/catch-all line residual:true — a residual line carrying a material share of the total is flagged for the owner, because that is exactly where a misread hides. NOT EVERY LINE IS A CATALOGUED PRODUCT, and an old document is full of the ones that are not: a delivery or transport charge, a labour or installation line, a service fee, a rounding line. Those still go through as ordinary lines — productRef is REQUIRED and must not be blank, so put the line's OWN wording in it ("Delivery charge"), and Taokeh CREATES that wording as a non-stock item (MD, 2026-09-09) so the document derives normally — the row is flagged, the created item is named for the owner, and it carries no stock and no price of its own. That is the designed path: it is not an error, so do not drop the line, do not fold its amount into another line, and do not invent a SKU for it. Omitting productRef altogether is the one thing that fails — the call is refused at the boundary before anything is staged. ⛔ ROW KEYS ARE STRICT (MD, 2026-09-09): a key the schema does not list is REFUSED BY NAME — with the key it probably meant, e.g. sell_priceunitPrice — and NOTHING is staged. Send the contract's apiField, not the spreadsheet header. Unknown keys used to be dropped in silence, so a set could stage "successfully" with its prices missing; that is the bug this refusal closes. NOT IN THE CATALOGUE? IT IS NOW: a line whose productRef matches NOTHING is created as a NON-STOCK item named after the line's own wording (no stock, no price of its own, marked as created by the migration), so the document derives and the owner reviews figures instead of a blocked row. Tell the owner which items were added — the reply names them. A ref that matches SEVERAL products is still flagged rather than duplicated.

ParametersJSON Schema
NameRequiredDescriptionDefault
linesYes
notesNoA SHORT note for the owner about this document — one or two sentences naming anything they should check. Not a place for lengthy reasoning.
partyNoThe customer (sales invoice) or supplier (purchase bill) name as printed. Matched against the existing contacts; a name matching several, or one that looks like shorthand for an existing contact, is flagged for the owner rather than guessed. Omit for a walk-in cash sale with no named customer.
docDateYesThe date the document was ORIGINALLY issued, YYYY-MM-DD. Never today unless it really was today — the whole point is that these documents keep their real dates.
docKindYes'sales_invoice' = an invoice this company ISSUED to a customer. 'purchase_bill' = a bill a supplier issued TO this company (inventory lines only, same rule as create_bill_draft). Other kinds are not supported yet.
partyIdNoThe Taokeh customer/vendor id, when you already resolved it with resolve_customer / resolve_vendor. Wins over `party`.
referenceNoThe document number exactly as printed in the old system (e.g. INV1603). Taokeh keeps it, so the customer's copy and yours still match. It must be unique in this company: a number already on the books is refused by name. Leave it out only if the document genuinely has no number. Before the first such invoice is entered, the owner must confirm where the real invoice series continues; Taokeh never silently starts migrated books at INV1.
needsReviewNoSet true when you want the owner to look at this one specifically. It is then held out of bulk approve and gets its own door.
sourceDocIdYesThe id this document has in the system you are migrating FROM — the primary key, row id or export id. THIS IS THE DEDUPE KEY: staging the same sourceDocId twice updates one row instead of booking the document twice, which is what makes re-running your export a no-op. If the old system has no id, use the document number, but use it consistently across the whole export.
sourceTotalNoThe grand total PRINTED on the source document. Advisory only — Taokeh re-derives its own figure and shows the two side by side, so the owner can see a whole batch tie to the old system's report. Send it whenever the paper states one; it is the single most useful check in the whole migration.
paymentMethodNo'CREDIT' (default) = it was on account, so it carries into receivables/payables. 'CASH' = it was settled at the counter. Get this right: it decides whether the document leaves a balance behind.
attachmentTokenNoThe ORIGINAL this document was read off — the photo of the handwritten cash-sale slip, the scanned invoice page. Call request_attachment_upload FIRST, PUT the raw bytes to its uploadUrl, then pass the token here (there is no inline base64 on this door: a backlog export would blow the context). The file rides the staged row, the owner sees it BESIDE your figures on the document's own review screen, and it lands on the posted invoice or bill automatically when they approve. Re-staging the same sourceDocId WITH a token replaces the file; re-staging without one leaves the file already there untouched, so a bare filing is repairable.

TDQS

A3.9/5.0
Behavior1/5

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

The description is otherwise exemplary — it discloses dedupe/update semantics, flag-and-hold behavior for unresolved lines, original number/date preservation, and the paper-attachment flow. However, it explicitly and emphatically asserts 'IDEMPOTENCY IS ON sourceDocId' while the annotation declares idempotentHint=false — a direct contradiction that could cause an agent to misjudge re-run safety or duplicate prevention. Per the rubric, a description contradicting annotations forces score 1.

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 earned — this tool carries migration, idempotency, cutover, ordering, and approval constraints that a short description could not convey. It is front-loaded with purpose and sibling differentiation, and the ALL-CAPS keyword markers (BULK, CUTOVER, ORDER MATTERS, PAPER) aid agent scanning. Docked slightly because some content is redundant with the already-rich schema (e.g., attachmentToken re-staging semantics restate the schema's story).

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 mutating 12-parameter tool with no output schema, the description covers nearly every operational behavior: closed-lane refusal with instructions, re-staging semantics, flag-and-hold of unsettled lines, owner-only changes after entry, and historical posting so Taokeh never e-invoices or chases the document. The one notable gap is that it never states what the call returns (staged row id/status), which matters more precisely because no output schema exists.

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 92% with already-rich property descriptions, so the baseline is 3. The description adds genuine operational meaning beyond the schema: sourceDocId as the key that makes re-running an export a no-op, sourceTotal as 'the single most useful check in the whole migration', residual lines flagged when they carry a material share, party matched 'flagged for the owner rather than guessed', and paymentMethod deciding 'whether the document leaves a balance behind'.

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 ('Bring ONE already-issued historical document... across from the system this company is migrating FROM') with the exact document kinds (sales invoice, supplier bill). Explicitly differentiates from sibling create_invoice_draft: 'it is NOT create_invoice_draft: nothing is posted, nothing is drafted for individual approval.' An agent can identify this as the bulk staging door 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 when-to-use ('ONLY for documents that were genuinely issued in the old system (or written in a paper book)'), when-not ('a NEW document belongs in create_invoice_draft / create_bill_draft'), and names the alternatives. Also covers the lane-open/pre-books-locked precondition, the cutover date rule (filter out documents on or before accounting start date), and the ORDER MATTERS instruction to stage supplier bills before sales invoices.

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

stage_master_dataStage master dataAInspect

Bring this company's MASTER DATA across from the system it is switching FROM: its CHART OF ACCOUNTS (every ledger code it keeps its books in), its PRODUCT CATALOGUE (every item it buys, stocks or sells, with the stock each was carrying at the cutover) or its CONTACT BOOK (every customer and supplier). Call intake_contract(doc_type: 'accounts' | 'products' | 'contacts') FIRST — it gives the exact fields, the rules and this company's own current counts. This WRITES NOTHING: the rows land on the owner's existing Import screens, where they confirm the columns and import them. THE UNIT IS THE WHOLE LIST: send every row of one kind in ONE call, and calling again for the same kind REPLACES the entire staged set rather than adding to it. Found a mistake? Send the corrected list in full. UNLIKE stage_opening_balances there is NO 'already imported' refusal, because master data is a CATALOGUE and not a ledger: the product upsert key is the SKU (an existing SKU is updated in place and ONLY the fields you actually sent are changed — a corrected three-field price list leaves its unit, barcode and buying-unit conversion untouched — its on-hand quantity is never touched by an import, and an opening quantity on a SKU that already exists is ignored), and contacts are de-duplicated case-insensitively by name — so staging a corrected list after an import is normal and double-counts nothing. OPENING STOCK IS THE ONE PART THAT TOUCHES THE BOOKS: a NEW SKU with both an opening quantity and a cost posts a real opening-stock journal entry (Dr Inventory / Cr Opening balance equity) when the owner approves, dated at this company's accounting start date while it is still migrating. Send the cutover quantity and the cutover cost, never a guess — a zero or missing cost still seeds the quantity but posts nothing. PRESENTATION FIELDS DO NOT MIGRATE: web addresses, storefront visibility and product images stay with the website, there is no field for them here, and you should TELL THE OWNER to keep those before the old system is switched off. Bill-of-materials links (combination SKUs built from components) are a separate sheet with their own review step and are NOT staged here — the owner uploads that sheet on the Import products page. Every contact row must say which side it is on (isCustomer / isVendor, or defaultRole for the whole list); Taokeh names any row that says neither straight back to you, so fix those before the owner sees the screen. THE CHART OF ACCOUNTS ('accounts') is the step to do FIRST, because the trial balance and every document afterwards land on its codes — and it is the quietest of the three: it writes NO journal line and carries NO figures, so opening balances still come across separately with stage_opening_balances(kind:'trial_balance'). Its key is the account CODE: an existing code is updated in place and keeps every posting attached to it, a new code is created, a code is never rewritten, and NOTHING IS EVER DELETED OR DEACTIVATED — an account missing from your list is simply left alone, so do not imply to the owner that it will disappear. A RENAME is always allowed on every account, including the ones Taokeh posts to automatically. A CHANGE OF TYPE OR NORMAL BALANCE IS REFUSED, row by row, on any account that already has postings or that a system role or bank account depends on, because it would silently restate reports the owner has already read and filed; intake_contract(doc_type:'accounts') marks exactly which accounts those are, so shape the list to avoid the refusal, and when a reclassification really is wanted, tell the owner the honest route — a new account plus a dated reclassification journal (create_journal_draft). THE COMPANY SETUP ('settings') is the LAST MILE: once the books are across, this is how the company itself stops being a form the owner types — its registered name, SSM registration number, TIN, address, state, statutory officer, the language it reads in, the measurement profile it prices by, and the date its books start. IT IS GOVERNED BY THE STRICT ALLOWLIST returned by intake_contract(doc_type:'settings'), and nothing outside it can be created: call intake_contract(doc_type:'settings') for the list, each key's meaning, its current value, and the settings an AI may NEVER write — payment credentials (a secret is never AI-written), publishing a storefront and advertising consent (outward and consent acts the owner takes), the AI and legal terms acceptances (an AI must never accept terms on the owner's behalf, least of all its own), the books lock (a money-integrity control) and every e-Invoice setting (they change statutory filing behaviour and follow the owner's own LHDN status). Those are refused BY NAME with the reason so you can tell the owner what to set rather than retrying. SEND ONLY WHAT THE OWNER TOLD YOU OR WHAT THE OLD SYSTEM PRINTS — an inferred TIN, registration number or employer number passes this import and fails at LHDN months later on a document that has already gone out; a blank is honest. The accounting start date is the highest-consequence key (it defines what counts as before the books started) and is refused if the company already has posted entries dated earlier; the measurement divisor is a NUMBER, not a label. Nothing is ever cleared: a setting missing from your list is left alone, and a row with a blank value is refused rather than read as 'erase this'. THE STAFF LIST ('employees') is the fifth kind and the one that behaves differently in two ways you must say out loud to the owner. It is ADMIN-ONLY — salaries and IC numbers are the most sensitive data in a company, and a non-admin connection is refused with the reason, deliberately. And ITS IMPORT CREATES RATHER THAN UPSERTS: employees have no unique key in Taokeh, so every ready row becomes a NEW person, anyone already in Taokeh must be left OFF the list, and a change to somebody who exists is made on their own employee page instead, or proposed by your AI with update_employee_draft. Use it for a whole payroll register being migrated AND for a single new hire the employer just described. SEND ONLY WHAT THE EMPLOYER ACTUALLY TOLD YOU: never construct or infer an IC number, a salary, a bank account, a date of birth or a statutory reference — a blank field is honest and gets filled in, a guessed one passes silently and then follows that person into EPF, SOCSO and LHDN submissions that have already gone out. A foreign employee has a passport and countryCode instead of an IC, with isMalaysian:false. The statutory flags DEFAULT ON when omitted (EPF, SOCSO, EIS, PCB, Malaysian, resident), exactly as the new-employee form does, so send false only on the employer's own word. Salary is MONTHLY and in ringgit. A date spoken loosely ('starting Monday') is yours to resolve to YYYY-MM-DD and to confirm back to them. Only ACTIVE staff consume a payroll seat: rows past the plan's allowance are reported as skipped at import rather than created, and historical leavers come across with status RESIGNED. This creates records only — it pays nobody, posts no journal line and files nothing; a payroll run is a separate act the owner takes afterwards. ⛔ ROW KEYS ARE STRICT (MD, 2026-09-09): a key the schema does not list is REFUSED BY NAME — with the key it probably meant, e.g. sell_priceunitPrice — and NOTHING is staged. Send the contract's apiField, not the spreadsheet header. Unknown keys used to be dropped in silence, so a set could stage "successfully" with its prices missing; that is the bug this refusal closes.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes'products' = the item list / catalogue. 'contacts' = the customer and supplier book. 'accounts' = the chart of accounts. 'settings' = the company setup; its complete stageable and owner-only classification is returned by intake_contract(doc_type:'settings'). 'employees' = the staff list; admin-only and create-only.
rowsYesEVERY row of the list, in the order the export prints them. This replaces any previously staged set for this kind.
sourceNameNoWhat you read — the export's file name or the report's own title, e.g. 'Item list export (Financio) — 412 items'. Shown to the owner as the evidence for what they are approving.
defaultRoleNocontacts only: the side a row that carries neither isCustomer nor isVendor lands on — the same choice the upload page offers as a Customers / Suppliers radio. Send it when the export is a single-sided list. Per-row flags always win over it.

TDQS

A4.8/5.0
Behavior5/5

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

The description extensively discloses behavioral traits beyond annotations: the tool writes nothing to books except opening-stock journal entries for new SKUs with cost; re-staging replaces the entire staged set; accounts are never deleted or deactivated; employees are create-only with no unique key; several settings are refused by name; statutory flags default on. This is far beyond what the annotations (readOnly/doesNotWrite/destructive flags) convey, adding critical side-effect and safety context.

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 description is extremely thorough and information-dense, but it is very long — arguably too long for a tool description — and uses heavy capitalization and parenthetical asides. While no sentence is wasted and critical details are front-loaded (kind behaviors, sequencing, write behavior), the sheer length and typographic noise reduce scannability for an agent. It earns a solid 3, not higher, because structure is front-loaded but conciseness suffers.

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

Completeness5/5

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

Given the tool's complexity — five kinds, massive parameter surface, sibling differentiation, legal/financial implications — the description is remarkably complete. It covers sequencing, prerequisites, alternatives, refusal conditions, side effects, owner-facing guidance, and per-kind semantics. Although there is no output schema, the description thoroughly explains what happens on staging and on approval, so an agent has sufficient context to invoke and interpret results.

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; however, the description adds substantial meaning beyond the schema: kind-specific behaviors (products upsert by SKU, contacts dedupe case-insensitively by name, accounts update by code, settings allowlist, employees create-only), refusal conditions, defaults, and cross-field rules (purchaseUnit must be sent with unitsPerPurchase; option1Value required with variantGroup). This significantly enhances parameter understanding beyond field-level schema descriptions.

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

Purpose5/5

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

The description clearly identifies the tool's function: bringing a company's master data across from an old system, enumerating the five kinds (chart of accounts, product catalogue, contact book, company settings, staff list) and distinguishing itself from stage_opening_balances. It names the resource, verb, and scope with precision, and explicitly differentiates this tool from its sibling stage_opening_balances.

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

Usage Guidelines5/5

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

The description provides explicit when-to-use guidance: call intake_contract(doc_type:...) first, use 'accounts' first, use stage_opening_balances for opening balances, use update_employee_draft for changes to existing employees, and states when not to use this tool (e.g., bill-of-materials links are staged separately; presentation fields do not migrate). It names alternatives and conditions clearly.

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

stage_opening_balancesStage opening balancesAInspect

Bring this company's OPENING BALANCES across from the accounting system it is switching FROM: its closing TRIAL BALANCE, its AGED RECEIVABLES (invoices customers still owed) or its AGED PAYABLES (bills still owed to suppliers). Call intake_contract(doc_type: 'trial_balance' | 'aged_receivables' | 'aged_payables') FIRST — it gives the exact fields, the rules, and for the trial balance this company's own chart of accounts. This posts NOTHING: the rows land on the owner's existing "Switch to Taokeh" review screens, where they match each account to their chart (trial balance) or check each party (aged lists) and post it themselves. THE UNIT IS THE WHOLE SET: send every row of one kind in ONE call, and calling again for the same kind REPLACES the entire staged set rather than adding to it — a trial balance only balances as a whole, so a partial patch would produce a set that ties to no report. Found a mistake? Send the corrected set in full. Taokeh re-derives every total from the rows you sent and shows it beside the total you say was printed on the report, so the owner can see the set tie to the cent; send that printed total in sourceTotal, and never adjust a row to make a total work — report the gap instead. THESE ARE THE CUTOVER, so unlike stage_document there is no "too old" fence: an aged invoice dated before the accounting start date is exactly right, and that is what makes it an opening document. REFUSED in two cases, both permanent until the owner acts: the books are LOCKED, or that kind's opening balances are ALREADY POSTED (staging over them would double-count — only the owner can undo them). A CREDIT balance on an aged list (an overpayment, an unapplied credit note) is not an opening invoice or bill: Taokeh will not enter it, so leave those rows out and TELL THE OWNER they exist, naming the party and the amount, so they can enter them by hand. ⛔ ROW KEYS ARE STRICT (MD, 2026-09-09): a key the schema does not list is REFUSED BY NAME — with the key it probably meant, e.g. sell_priceunitPrice — and NOTHING is staged. Send the contract's apiField, not the spreadsheet header. Unknown keys used to be dropped in silence, so a set could stage "successfully" with its prices missing; that is the bug this refusal closes.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes'trial_balance' = the closing balances of every account in the old system. 'aged_receivables' = the invoices customers still owed at the cutover, one row each. 'aged_payables' = the bills still owed to suppliers, one row each.
rowsYesEVERY row of the set, in the order the report prints them. This replaces any previously staged set for this kind.
sourceNameNoWhat you read — the export's file name or the report's own title, e.g. 'Trial Balance as at 31-12-2025 (Financio)'. Shown to the owner as the evidence for what they are approving.
sourceTotalNoThe grand total PRINTED on the report (for a trial balance, the DEBIT total). Advisory: Taokeh re-derives its own figure and shows the two side by side. This is the single most useful check in the whole migration — send it whenever the report states one.
sourceTotalCreditNotrial_balance only: the CREDIT total printed on the report, if it is stated separately.

TDQS

A4.9/5.0
Behavior5/5

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

The description goes far beyond the sparse all-false annotations: it discloses that the tool posts NOTHING to the ledger, that calling again for the same kind REPLACES the entire staged set, that totals are re-derived, and that refusal cases are permanent until the owner acts. The replacement semantics do not contradict destructiveHint=false because replacement affects only the temporary staged set, not finalized accounting 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?

The description is long but front-loaded and every paragraph adds a distinct operational rule. The all-caps emphasis aids scanning, though tighter organization would make it easier to parse. There is little filler, but the length itself keeps it from being maximally concise.

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

Completeness5/5

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

For a high-stakes migration tool with five parameters and no output schema, the description covers prerequisites, replacement semantics, refusal conditions, credit-balance handling, date-format pitfalls, and post-call owner review behavior. An agent has enough context to invoke the tool correctly and predict what happens next.

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?

Although the schema already covers parameters at 100%, the description adds critical meaning beyond field names: rows must be the whole printed set, part-paid invoices must send outstanding rather than original amount, credit rows are not entered, debit/credit omission means a section heading, and sourceTotal is advisory but the single most useful check. This materially improves correct 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?

The description states a specific verb+resource: bring the company's opening balances (trial balance, aged receivables, aged payables) across from the old accounting system. It clearly distinguishes this from stage_document by emphasizing the cutover context and the absence of the 'too old' fence, so the agent can tell it apart from siblings.

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

Usage Guidelines5/5

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

It explicitly instructs the agent to call intake_contract(doc_type: ...) FIRST and names the exact doc_type values. It provides strong when-to-use vs. when-not-to-use guidance: use it for cutover balances, do not use it when books are locked or the kind is already posted, and leave out credit rows while informing the owner.

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

stock_levelStock levelsA
Read-only
Inspect

How many units of a product you have on hand right now — search by product name or SKU. If this company uses Counter (the till), the figure is as at the last day-close: counter sales move stock once, when the day is closed, not at each scan.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYes

TDQS

A4.1/5.0
Behavior4/5

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

Beyond the readOnlyHint annotation, the description adds a non-obvious behavioral detail: counter sales do not decrement stock at the moment of sale, only at day-close. This is valuable context that prevents incorrect interpretation of the returned figure.

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

Conciseness5/5

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

Two sentences, both purposeful: the first states the result and accepted inputs, the second adds the important Counter timing caveat. The description is front-loaded, scannable, and contains no filler.

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 simple one-parameter read-only lookup, the description is nearly complete: it explains what to search by, what the value represents, and when the value may be stale. It does not describe the exact output shape, but the phrase 'how many units' gives enough expectation for this tool's simplicity.

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

Parameters4/5

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

With schema coverage at 0%, the description carries the full burden for explaining 'query.' It does so by stating that the query can be a product name or SKU, which is meaningful semantic guidance beyond the raw string schema.

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

Purpose4/5

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

The description clearly identifies the tool as a current on-hand stock lookup, searchable by product name or SKU. It avoids ambiguity with sibling history/listing tools by emphasizing 'right now,' though it does not explicitly name an alternative.

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 practical search guidance ('search by product name or SKU') and explains an important timing condition for Counter users: stock reflects the last day-close. It stops short of contrasting with alternatives such as stock_movements or low_stock, so it is clear but not exhaustive.

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

stock_movementsStock movementsA
Read-only
Inspect

Read the STOCK MOVEMENT LEDGER in bulk — every recorded change to on-hand quantity, across products, in one call. stock_level says how many you have RIGHT NOW for one product; this says WHAT MOVED, WHEN, WHY and WHAT IT LEFT BEHIND. Use it for stock-turn analysis, shrinkage hunting, reorder timing, or reconstructing how a balance got where it is. Every filter is optional and a bare call is a legitimate "what moved lately" pull: narrow with product (case-insensitive contains against the product name OR SKU), from/to (the movement date window, in Malaysian time) and sourceType (exactly one cause — see the list). Each row: ts, product {sku, name}, qtyDelta (signed — negative took stock out), balanceAfter (on-hand immediately after that move, as the posting path recorded it), unitCost, reason (free text the person typed, where there was one), sourceType and sourceId (the id of the document that moved it — pair it with search_documents to see which one). ⚠ WHICH MOVEMENTS EXIST AT ALL DEPENDS ON THIS COMPANY'S STOCK MODE, and the answer says which mode it is in (stockMode) with a note. In modified_periodic — the DEFAULT — selling does NOT move stock: invoices, delivery orders and credit notes write no movement row, and stock is trued up at stock take. Seeing no 'sale' rows there means the company is periodic; it does NOT mean nothing was sold, and it is NOT shrinkage. Only a perpetual company has sale / sale_void / credit_note rows. Read the mode before you interpret the rows. balanceAfter is the total across the whole company, not per location; on a multi-location company each row also carries location. Rows come back newest first, capped at 200 with total, shown and more — when more is true, narrow by date and pull the periods in turn rather than treating a partial page as the whole. Values are verbatim as recorded at the time, never re-derived. ⛔ WHAT IT WILL NOT DO: it does not value your inventory (balance_sheet does), does not compute COGS or margin (income_statement, profit_drivers), and does not tell you what to reorder (low_stock). Nothing is written, and no draft is created.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoLatest movement date (YYYY-MM-DD, Malaysian time).
skuNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
dateNoNOT a filter on this tool. Pass a date WINDOW as `from` and/or `to` (YYYY-MM-DD). A single date is `from` and `to` set to the same day.
fromNoEarliest movement date (YYYY-MM-DD, Malaysian time). The main way to break a >200-row pull into honest slices.
itemNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
nameNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
typeNoNOT a filter on this tool. Pass the movement cause as `sourceType`.
limitNoNOT a filter on this tool. The page size is fixed at 200 movements. Narrow with from/to, product or sourceType and pull the periods in turn.
queryNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.
dateToNoNOT a filter on this tool. Pass the end of the window as `to`.
reasonNoNOT a filter on this tool. `reason` is free text the person typed and is RETURNED on each row, not a filter. To narrow by cause use `sourceType` (e.g. 'adjustment').
sourceNoNOT a filter on this tool. Pass the movement cause as `sourceType`.
productNoCase-insensitive contains matched against the product NAME or SKU. Omit for every product.
dateFromNoNOT a filter on this tool. Pass the start of the window as `from`.
productIdNoNOT a filter on this tool. This search matches product TEXT, not ids — pass the name or SKU as `product`.
sourceTypeNoExactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual company.
productNameNoNOT a filter on this tool. Pass it as `product` — one case-insensitive contains matched against BOTH the product name and the SKU.

TDQS

A4.9/5.0
Behavior5/5

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

Beyond the readOnlyHint=true annotation, the description discloses crucial behavioral traits: row cap at 200 with total/shown/more, newest-first ordering, stock-mode dependence, balanceAfter being company-wide, and values being verbatim as recorded. It also states 'Nothing is written, and no draft is created,' reinforcing the read-only safety profile. This is rich, non-obvious context that annotations alone 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.

Conciseness5/5

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

The description is long but every sentence earns its place: purpose, use cases, filter semantics, row format, the critical stock-mode caveat, pagination behavior, and explicit exclusions. It is front-loaded with the core purpose, uses structured warnings and a clear 'WHAT IT WILL NOT DO' section, and avoids repetition or 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?

For a tool with no output schema and many subtle behavioral traps, the description is exceptionally complete. It covers return fields, signed quantity semantics, balanceAfter scope, location presence, pagination handling, stock mode interpretation, and how to follow sourceId to search_documents. An agent has everything needed to call this correctly and interpret results properly.

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 each parameter. The description adds genuinely useful parameter semantics beyond that: every filter is optional, product matches case-insensitively against name OR SKU, from/to define a Malaysian-time window, and from is 'the main way to break a >200-row pull into honest slices.' This is more than the schema-only baseline, though the schema still carries most of the parameter documentation load.

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 and resource: 'Read the STOCK MOVEMENT LEDGER in bulk — every recorded change to on-hand quantity, across products, in one call.' It clearly differentiates itself from stock_level by contrasting 'how many RIGHT NOW' with 'WHAT MOVED, WHEN, WHY and WHAT IT LEFT BEHIND.' This makes the tool's identity unambiguous even among many sibling 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?

The description gives concrete use cases (stock-turn analysis, shrinkage hunting, reorder timing, reconstructing a balance) and explicitly states what it will NOT do, naming the correct sibling tools for those jobs (balance_sheet, income_statement, profit_drivers, low_stock). It also explains when a bare call is legitimate and how to narrow it, giving clear operational guidance.

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

tax_positionTax positionA
Read-only
Inspect

Your current tax posture in one read: (1) SST — the current bi-monthly period's SST payable if you're SST-registered (registration 'none' ⇒ not registered, nothing to remit); and (2) e-invoice consolidation — whether monthly consolidation is on, the open month, last month's filing due date, and whether last month's consolidated document is generated / LHDN-validated. Basis: SST-02 return figures + the consolidated-e-invoice register.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false. The description adds value by detailing the specific data sources (SST-02 return figures, consolidated-e-invoice register) and explaining edge cases like registration 'none' meaning no remittance. It does not contradict the annotations and provides meaningful behavioral context beyond safety.

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 well-structured with a colon and numbered items, front-loading the core purpose. It is a single long sentence but each clause carries essential information, and there is no redundant filler. Minor complexity from nested clauses prevents a perfect score.

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 must serve as the primary documentation of return values. It covers both major sections (SST status and e-invoice consolidation) and their key fields, including dates and validation status. It omits minor formatting details but is adequate for a read-only status check.

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

Parameters4/5

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

The tool has zero parameters, so the schema provides complete coverage (100%). The description focuses on the output rather than parameters, which is appropriate. It explains the meaning of the returned data, which is the relevant semantic content here.

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

Purpose5/5

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

The description clearly identifies a specific resource (tax position) and a specific read action ('one read'), and enumerates the exact components (SST payable and e-invoice consolidation) it returns. This distinguishes it from sibling financial reports like cash_position or business_snapshot, which cover different domains.

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

Usage Guidelines2/5

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

The description does not provide any guidance on when to use this tool versus alternatives, nor does it mention related tools or conditions that would make it the appropriate choice. The phrase 'in one read' implies a quick lookup, but no explicit context, exclusions, or alternatives are given.

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

update_contact_draftFile a pending contact-change draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose changes to a customer or vendor ALREADY in Taokeh — the correction door for an address book with missing tax ids, stale phone numbers or wrong e-Invoice flags (e.g. after a migration). This does NOT change anything: it files a pending DRAFT the owner reviews as a DIFF (current → proposed, changed fields only) and approves with one tap; only that tap writes. Pass partyKind ('customer' or 'vendor'), the contact's REAL contactId from resolve_customer / resolve_vendor — a name is refused, because a near-match would edit the wrong company — and proposed, an object holding ONLY the fields you want changed. Settable fields, mirroring the contact screen exactly: name, email, phone, address, tin (Tax ID), brn (registration no.), idType ('BRN' or 'NRIC'); on a CUSTOMER also requiresEinvoice, einvCity, einvPostcode, einvState (LHDN 2-digit code), remindersMuted; on a VENDOR also selfBill, alwaysExpense, state. Pass null on a text field to CLEAR it. Anything else is refused by name — do not invent fields. You cannot move a contact between customer and vendor here; they are separate records. A field the contact already agrees with is dropped, and a proposal that changes nothing is refused rather than filed as an empty diff for a human to tap. One contact per call — loop for a sweep, because 100 reviewable diffs is the point: the owner sees each change before it lands. BE HONEST: never guess a tax id or a phone digit; if you are unsure, leave the field out and say so in notes with needsReview. If the record has been edited since you read it, the owner is shown BOTH values and the one-tap approval is refused — that is by design; call revise_draft (kind 'contact_update') to re-read and re-propose.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note, in the reviewer's language: what you changed and why, and anything they should double-check. Leave empty when there is nothing to flag.
personsNoChanges to the PEOPLE filed under this contact (the individuals you deal with there). Each entry is one change. A removal names only personId. A person needs a name to be added. These ride the SAME draft and the SAME single approval as the field changes — the owner sees a removal shown as a removal, in words.
proposedNoONLY the fields you want changed. A field the contact already agrees with is dropped; an unknown or wrong-side field is refused by name. Omit it entirely when you are only changing the PEOPLE below.
contactIdYesREQUIRED — the contact's real id from resolve_customer / resolve_vendor. A name is refused: editing the wrong company silently is worse than asking.
partyKindYesWhich side of the book the contact is on: 'customer' (someone you sell to) or 'vendor' (someone you buy from). They are separate records — this tool cannot move one to the other.
needsReviewNoSet true when something gave you pause — a tax id you read off a blurry document, a phone number the user was unsure about. It flags the draft for the reviewer.

TDQS

A4.7/5.0
Behavior5/5

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

The description discloses far more than annotations alone: nothing changes until human approval, the owner sees a diff, unchanged fields are dropped, empty proposals are refused, stale edits cause one-tap approval to be refused, and unknown fields are rejected by name. It also warns against guessing tax ids or phone digits. This is exceptionally transparent for a mutation-like 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 long but information-dense, and the most critical constraint — 'FILES A PENDING DRAFT ONLY' — is front-loaded. Some repetition exists between the first and second sentences, and the '100 reviewable diffs is the point' phrase is slightly indirect. Overall the length is justified for a safety-critical correction 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?

The description covers the core workflow, human-approval behavior, conflict handling, field constraints, and honesty rules, which is excellent context. But it omits the persons sub-resource entirely and, with no output schema, does not describe what a successful call returns. The schema details persons well, but the description itself is not 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, and the description adds important semantic context: contactId must be a real id and names are refused, proposed should contain only changed fields, null clears a text field, and wrong-side fields are refused. It also connects notes and needsReview to honesty behavior. However, it does not mention the persons parameter at all, so it is not a complete parameter-semantics treatment.

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 ('files a pending draft'), a specific resource (contact-change correction in Taokeh), and clearly separates this from creation: 'customer or vendor ALREADY in Taokeh — the correction door'. It also distinguishes itself from related workflows by naming resolve_customer, resolve_vendor, and revise_draft.

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 explicitly tells the agent when to use this tool (correcting existing contacts with missing tax ids, stale phones, wrong e-Invoice flags), when not to use it ('cannot move a contact between customer and vendor'), and what to do instead in a conflict ('call revise_draft (kind 'contact_update')'). It also gives scope guidance: one contact per call and loop for a sweep.

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

update_employee_draftFile a pending employee-change draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose corrections to an employee ALREADY in Taokeh's payroll — a wrong IC or passport number, a missing EPF/SOCSO/income-tax number, a salary keyed a digit out, a stale designation, the statutory applicability flags. This does NOT change anything: it files a pending DRAFT an admin reviews as a DIFF (current → proposed, changed fields only) and approves with one tap; only that tap writes. Pass the employee's REAL employeeId — from payroll_summary with staff: true (the whole roster, works even before the first payroll run) or perEmployee: true — and proposed, an object holding ONLY the fields you want changed. A name is refused: two people can share one, and editing the wrong person's salary silently is much worse than asking. ⚠ FORWARD ONLY, and you must tell the user this: an approved change applies to FUTURE payroll runs. It never re-opens, recomputes or restates a payslip or payroll run that has already been filed — including the year-to-date PCB, which is summed from payslips already submitted. If a filed month is wrong, that is a human decision taken in Payroll → Payroll Runs, not something this tool can do. Settable fields, mirroring the employee form exactly: staffNo, name, icNo, passportNo, countryCode, dateOfBirth, designation, joinDate, resignDate, status ('ACTIVE' or 'RESIGNED'), email, isMalaysian, basicSalary, epfEmployeeRate, bankName, bankAccountNo, epfNo, socsoNo, incomeTaxNo, epfApplicable, socsoApplicable, eisApplicable, pcbApplicable, skbbkEnrolled, maritalStatus ('SINGLE', 'MARRIED' or 'SINGLE_PARENT'), spouseWorking, numChildren, taxResident, residencyChangeMonth ('YYYY-MM'), zakatMonthly, employmentStatus (CP8D code '1'–'6'), contractEndDate, holidayState, notes. NOT settable here, each refused by name with the screen that owns it: the TP3 prior-employer figures (a signed declaration, and requesting one EMAILS the employee), the TP2 benefits-in-kind values (owned by the approved election), and the flat-15% tax regime (approval-conditional — an AI cannot verify it, and halving somebody's tax is not a diff-door change). bankName and bankAccountNo ARE settable because they print on the payslip and on the giro list the owner uploads at their own bank — TAOKEH NEVER PAYS ANYONE; the owner authorises every payment at their own bank, and nothing on this connector can move money. A field the record already agrees with is dropped, and a proposal that changes nothing is refused rather than filed as an empty diff. One employee per call — loop for a sweep, because each reviewable diff is the point. BE HONEST: never guess an IC, a bank account or a salary; leave the field out and say so in notes with needsReview. ADMIN ONLY: payroll sits behind its own role and this tool refuses on any other connection.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note, in the reviewer's language: what you changed, why, and what they should double-check.
proposedYesONLY the fields you want changed. A field the record already agrees with is dropped; an unknown or deliberately-excluded field is refused by name.
employeeIdYesREQUIRED — the employee's real id, from payroll_summary (`staff: true` for the roster, or `perEmployee: true` for a run). A name is refused.
needsReviewNoSet true when something gave you pause — an IC read off a blurry photo, a salary the user was unsure about.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations provide no hints (all false), so the description carries the full burden. It clearly discloses draft-only semantics, human approval flow, forward-only application, non-retroactivity, refusal behaviors (name, empty diff, admin-only), that Taokeh never pays anyone, and the honesty rule about guessing sensitive fields.

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 description is front-loaded with the most critical fact — draft-only, nothing changes until approval — but it is very long and repeats information already in the schema: the settable-fields list, the name-refusal rule, employeeId source, and the Taokeh-never-pays disclaimer all appear in both. Useful but somewhat bloated.

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

Completeness5/5

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

For a complex payroll tool with no output schema, the description is complete: it covers the full call workflow, field semantics and restrictions, forward-only consequences, reviewer expectations, admin permission model, and per-call behavior. An agent has everything needed to invoke 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% and most parameters already have descriptions, so baseline is 3. The description adds meaningful usage context beyond the schema: where to obtain employeeId (payroll_summary with staff:true or perEmployee:true), that proposed must contain only changed fields, that agreeing fields are dropped, and that needsReview marks uncertain values.

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: it files a pending employee-change draft for an employee already in Taokeh's payroll, and nothing changes until a human approves. It clearly distinguishes itself from sibling update_*_draft tools by focusing on employee corrections, and even enumerates the exact kinds of corrections intended.

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

Usage Guidelines5/5

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

Explicitly tells when to use the tool (corrections to an existing employee, from payroll_summary) and when not to (fixing a filed payroll month is a human decision in Payroll → Payroll Runs). It also states exclusions by name (TP3, TP2, flat-15% regime), admin-only access, and the one-employee-per-call rule with looping guidance.

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

update_invoice_draftFile a pending correction draft for a posted invoice (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose a correction to an invoice ALREADY POSTED in Taokeh — the door for an invoice that went onto the books with a wrong line, a wrong date or the wrong payment method. This does NOT change anything: it files a pending DRAFT an ADMIN reviews as a DIFF (current → proposed) and approves; only that tap rewrites the invoice, and it keeps the SAME invoice number, the original attached document and any payment-reminder history. Pass saleId, the invoice's REAL id from search_documents — an invoice number is refused, because two documents can carry the same printed number and correcting the wrong one is worse than asking. ROUTING — three different mistakes, three different doors, and picking the wrong one is expensive. (1) THE SALE NEVER HAPPENED (keyed twice, entered on the wrong company, cancelled before delivery): the owner VOIDS it — Sales → the invoice → Void, in Taokeh. There is deliberately NO AI lane for voiding; erasing a document from the books is a person's decision at the screen. Tell them where to click. (2) THE SALE HAPPENED BUT THE INVOICE IS WRONG (a wrong line, a wrong quantity or price, the wrong date, the wrong payment method): THIS tool. (3) SOMETHING CHANGED AFTER THE SALE (goods came back, a price was renegotiated, a discount was agreed later): create_credit_note_draft — a real event that belongs on the books as its own document, not an erasure of history. WHAT YOU CAN CHANGE: saleDate, paymentMethod ('CASH' or 'CREDIT'), refNo (the customer's own reference / PO number), term (the payment term, stored as written), dueDate (only when the due date ITSELF is wrong — correcting just the invoice date already moves the due date by the same number of days, so the agreed credit period survives), and lines — the FULL REPLACEMENT SET, so send every line the invoice should have, including the ones that were already right. ON A MEASUREMENT COMPANY, do NOT send the small negative rounding line the engine adds under a per-foot line: it is Taokeh's own line, not one of the invoice's, it is preserved untouched by a header-only correction, and it is re-derived from whatever timber line you do send. You cannot mark a line as one either — that is a fact Taokeh reads off the document, never something a caller asserts. WHAT YOU CANNOT, each refused by name: the CUSTOMER (a different customer is a different document — credit this one and raise a new invoice to the right party); the INVOICE NUMBER (preserved across an edit; Taokeh's own Edit screen cannot change it either); and the lines of an invoice that spreads its revenue over time under MFRS 15 (which new line inherits which schedule is a guess, and a guess about deferred revenue is not something a reviewer can check on a diff — header-only corrections still work and keep the schedule intact). SEVEN THINGS BLOCK AN EDIT OUTRIGHT, checked when you file and again when the admin taps, and each refusal names the real next step: the document is not an invoice; it is validated on MyInvois; it has been submitted to LHDN; a credit note or a debit note has been raised against it; it was consolidated from delivery orders; a payment has been allocated to it. A proposal that changes nothing is refused rather than filed as an empty diff for a human to tap. If the invoice is edited by someone else after you read it, the admin is shown BOTH versions and the one-tap approval is refused — that is by design; call revise_draft (kind 'invoice_update') to re-read and re-propose.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note in the reviewer's language: what was wrong, what you changed, and anything they should double-check before they approve a rewrite of a posted document.
saleIdYesREQUIRED — the posted invoice's real id, from search_documents. An invoice number is refused: correcting the wrong document silently is worse than asking which one they mean.
proposedYesONLY what you want changed. An unknown or not-patchable key is refused by name; a proposal the invoice already agrees with is refused rather than filed.
needsReviewNoSet true when something gave you pause — a quantity you inferred, a price the user was unsure about. It flags the draft for the reviewer.
printedTotalNoThe grand total the corrected invoice should show, if the user told you one — cross-checked against the server's own derivation and flagged on the review screen. Reconcile a disagreement in chat; never quietly average the two.

TDQS

A4.9/5.0
Behavior5/5

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

The description discloses far more than annotations: no immediate mutation, human review as a diff, preservation of invoice number and attachments, double-checked blockers, refusal of no-op proposals, and concurrent-edit behavior. The readOnlyHint=false annotation is consistent with filing a pending draft; there is no contradiction.

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

Conciseness4/5

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

The description is long and dense, but the core constraint is front-loaded and headings like ROUTING, WHAT YOU CAN CHANGE, and WHAT YOU CANNOT make it scannable. It loses a point for restating some schema-level parameter guidance and for saying 'SEVEN THINGS' while enumerating only six blockers.

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 tells the agent everything needed to invoke correctly: effect, required identifier source, editable and non-editable fields, blocking conditions, and next-step routing. It is unusually complete for a high-complexity tool.

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?

Even with 100% schema coverage, the description adds significant parameter-level meaning: saleId must be the real document id rather than printed number, lines are a full replacement set with a measurement-company rounding-line caveat, term/dueDate interactions are explicit, and exclusions such as customer, invoice number, and MFRS15 lines are spelled out.

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

Purpose5/5

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

The description opens with a precise statement: it files a pending correction draft for a posted invoice, and nothing changes until a human approves it in Taokeh. It clearly distinguishes itself from related siblings by naming the voiding path and create_credit_note_draft for post-sale changes.

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

Usage Guidelines5/5

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

The ROUTING section explicitly maps three different mistake types to three different doors: manual void in Taokeh for sales that never happened, this tool for wrong posted invoices, and create_credit_note_draft for post-sale changes. It also lists concrete blockers, refusal cases, and directs the caller to revise_draft when a concurrent edit blocks approval.

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

update_logo_draftFile a pending logo-change draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose a new COMPANY LOGO for this company — the mark Taokeh prints on every invoice, quote, receipt and statement it generates, and that fronts the online storefront. This does NOT change anything: it files a pending DRAFT an ADMIN reviews by looking at the logo they have now beside the one you are proposing, and approves with one tap; only that tap sets it. Send the image one of two ways, never both. Lane 1 (default, any size): call request_attachment_upload, PUT the raw bytes to its uploadUrl, and pass the returned attachmentToken here. Lane 2 (fallback): if your shell cannot reach taokeh.my — sandboxed clients sit behind a network allowlist and the PUT fails 403/blocked; that is YOUR sandbox, not Taokeh — send attachmentBase64 + attachmentMediaType inline instead, always with attachmentBytes (the file's decoded size on disk) so a truncated paste is rejected rather than filed. PNG or JPEG only: those are the only formats Taokeh can embed in a generated PDF, and anything else is refused by name. Taokeh SHRINKS oversized artwork for you rather than sending you away to resize it — a 5000×5000 export is accepted and stored at 2000px, and the review screen says so; only an image so large it is no longer a logo is refused. A LOGO IS ONE VALUE, so the proposal REPLACES the whole thing rather than patching it, and there is only ever ONE logo proposal waiting: filing a second one replaces the first, which is rejected as superseded. If the company already has a logo the review page shows both images side by side; if it has none, this is the first one. If an admin sets or removes a logo in Taokeh after you file, the one-tap doors refuse and send them to the full review page — a human's own choice is never overwritten by a proposal that never saw it. ⛔ THIS IS THE COMPANY LOGO ONLY. It is not the Pioneer program's testimonial artwork, and nothing on this connector can touch that. BE HONEST: propose only an image the user actually gave you for this purpose. Never generate a logo and file it as though they had chosen it, and tell them in the same breath that nothing on their paperwork changes until they tap Approve.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note, in the reviewer's language: where this image came from and what they should check before it goes on their invoices.
needsReviewNoSet true when something gave you pause — an image you are not certain is the right mark, or one the user sent in passing rather than chose.
attachmentBytesNoThe decoded byte size of the image on disk — send it alongside attachmentBase64 and the server rejects a truncated paste instead of filing half a logo.
attachmentTokenNoThe token from request_attachment_upload, AFTER you have PUT the image bytes to its uploadUrl. The preferred lane for any real logo file. Mutually exclusive with attachmentBase64.
attachmentBase64NoThe logo image as base64 — the fallback lane, for when your shell cannot reach taokeh.my. PNG or JPEG only. Mutually exclusive with attachmentToken.
attachmentSha256NoThe SHA-256 of the image as 64 hex chars — optional second integrity check alongside attachmentBase64.
attachmentFilenameNoThe original file name, e.g. 'acme-logo.png'. Shown on the review page so the admin recognises what they were sent.
attachmentMediaTypeNoThe image's MIME type — 'image/png' or 'image/jpeg'. Required when attachmentBase64 is given.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations are all false and carry almost no signal, so the description carries the full burden — and it delivers richly: supersede semantics ('filing a second one replaces the first, which is rejected as superseded'), shrink behavior ('5000×5000 export is accepted and stored at 2000px'), format refusal ('anything else is refused by name'), sandbox-induced PUT 403s, truncated-paste rejection via attachmentBytes, and human-override protection ('a human's own choice is never overwritten by a proposal that never saw it'). No contradiction with the annotations — destructiveHint=false aligns with 'This does NOT change anything'.

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 the density of decision-relevant information justifies it: every major block (pending semantics, two lanes, formats, shrinking, one-value replacement, human-override, scope boundary, honesty rule) maps to a distinct risk the agent must handle. Critical info is front-loaded ('FILES A PENDING DRAFT ONLY') and warnings are scannable via caps and the ⛔ marker. Minor deductions for redundancy ('This does NOT change anything' restates the opening sentence) and an editorial aside ('that is YOUR sandbox, not Taokeh').

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 complex tool — 8 parameters, two mutually exclusive input lanes, no output schema, no idempotency — the description covers purpose, exact invocation mechanics, side effects, concurrency behavior, failure modes, and ethical constraints. The only notable gap is the success response: nothing states what the agent should expect back after filing (e.g., a draft identifier or confirmation), which matters more because there is no output schema. That single omission keeps this from a 5.

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 workflow-level meaning beyond the schema: it groups parameters into two mutually exclusive lanes (attachmentToken alone vs attachmentBase64 + attachmentMediaType + attachmentBytes), explains why attachmentBytes is mandatory alongside base64 ('a truncated paste is rejected rather than filed'), and states the format constraint ('PNG or JPEG only'). It adds little on notes, needsReview, attachmentSha256, or attachmentFilename, but those are already well documented 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 first sentence states a specific verb and resource with a decisive qualifier: 'FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose a new COMPANY LOGO.' The title independently confirms it ('File a pending logo-change draft'). It also differentiates from siblings by fencing off the Pioneer testimonial artwork ('THIS IS THE COMPANY LOGO ONLY'), so an agent cannot confuse it with the large create_*_draft / update_*_draft family.

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 and how-to-use guidance with named alternatives: Lane 1 directs the agent to call request_attachment_upload (a sibling) and pass its attachmentToken; Lane 2 specifies the exact fallback condition ('if your shell cannot reach taokeh.my... PUT fails 403/blocked') and the parameters to use instead. Scope exclusions are explicit ('It is not the Pioneer program's testimonial artwork'), and the honesty rule states when NOT to file ('Never generate a logo and file it as though they had chosen it').

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

update_product_draftFile a pending product-change draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose corrections to a product ALREADY in Taokeh's catalogue — a selling price keyed wrong, a name that came across from the old system mangled, a missing barcode, the wrong unit, a reorder point nobody set, an item filed under the wrong category. This does NOT change anything: it files a pending DRAFT the owner reviews as a DIFF (current → proposed, changed fields only) and approves with one tap; only that tap writes. Name the product with productId (the id resolve_product returns) or with its EXACT sku — a SKU is unique inside a company, so it is an exact key; a product NAME is not, and is refused. If you pass both and they disagree, the call is refused rather than guessing. proposed holds ONLY the fields you want changed: name, unit, unitPrice, reorderPoint, barcode, and the category (pass categoryId, or category as a name matched against the categories the company ALREADY has — this tool will never create a category, because the owner is approving a change to a product, not new master data). ⛔ WHAT IT CANNOT DO, each refused by name with the screen that owns it: it cannot change STOCK ON HAND — a quantity change moves inventory and cost of goods sold together, so Taokeh only takes it at Products → Adjust stock where a counted reason is required; it cannot change the AVERAGE COST, which the purchases that set it own and which is what the inventory is worth on the balance sheet, so an edit here would restate that value with no journal behind it; it cannot change the SKU, the key everything else resolves on; it cannot set a description, which the product page has no control for at all (the catalogue import does); and it cannot publish or unpublish the item to the online shop, because what strangers can see and buy is not something an AI proposal should decide. A field the record already agrees with is dropped, and a proposal that changes nothing is refused rather than filed as an empty diff. One product per call — loop for a sweep, because each reviewable diff is the point. BE HONEST: never guess a price or a barcode; leave the field out and say so in notes with needsReview.

ParametersJSON Schema
NameRequiredDescriptionDefault
skuNoThe EXACT SKU, as an alternative to productId. Exact only — a near miss is refused, and a product NAME is never accepted.
notesNoA SHORT reviewer note, in the reviewer's language: what you changed, why, and what they should double-check.
proposedYesONLY the fields you want changed. A field the record already agrees with is dropped; an unknown or deliberately-excluded field is refused by name.
productIdNoThe product's real id, from resolve_product. Give this OR `sku`.
needsReviewNoSet true when something gave you pause — a price the user was unsure about, a barcode read off a blurry photo.

TDQS

A5/5.0
Behavior5/5

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

With only generic boolean annotations, this description carries the full behavioral burden and does it superbly. It discloses the pending-draft semantics, that nothing changes until a human approves the diff, that agreeing fields are dropped, that an empty proposal is refused, that conflicting productId/sku keys are refused, and that unsupported fields are refused by name. This goes far beyond what any annotation could convey.

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

Conciseness5/5

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

The description is long, but every sentence earns its place. It is front-loaded with the critical pending-draft-only warning, then organizes allowed fields, explicit impossibilities, conflict behavior, and guidance. The use of all-caps headings, examples, and a clear refusal list makes the density navigable rather than bloated.

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

Completeness5/5

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

Given the nested proposed object, five parameters, no output schema, and sparse annotations, the description covers everything needed to invoke the tool correctly: how to identify the product, which fields may change, how categories work, what triggers refusals, what to do with uncertain data, and how to handle batch sweeps. No critical context for 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%, so the baseline is 3, but the description adds substantial meaning beyond the schema. It explains why productId versus exact sku are both valid exact keys, that a product name is refused, that proposed contains only changed fields, that category names are matched against existing categories and never created, and that barcode can be null to clear it. It also ties notes and needsReview together with the honesty requirement.

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 ('files a pending draft'), a specific resource (a product already in Taokeh's catalogue), and the approval workflow that distinguishes it from direct writes. It also clearly scopes what it is not: it does not create products, change stock, cost, SKU, description, or publishing state. This makes it easily distinguishable from the many create_*_draft, update_*_draft, and resolve_* siblings.

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

Usage Guidelines5/5

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

The description explicitly says when to use it: propose corrections to an existing catalogue product, and even gives concrete examples like a miskeyed price, mangled name, missing barcode, or wrong category. It also gives explicit non-uses, each with the owning screen or workflow (stock adjustment, purchases, catalogue import), plus procedural guidance to loop per product because each reviewable diff is the point.

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

update_recurring_invoice_draftFile a pending recurring-invoice change draft (human approves in Taokeh)AInspect

FILES A PENDING DRAFT ONLY — NOTHING CHANGES UNTIL A HUMAN REVIEWS AND APPROVES IT IN TAOKEH. Propose changes to a recurring invoice ALREADY set up in Taokeh — a price rise across a subscription, a changed quantity, a new end date, a cadence correction, or PAUSING the billing. This does NOT change anything: it files a pending DRAFT the owner reviews as a DIFF (current → proposed, changed fields only) and approves; only that tap writes. Name the schedule with recurringId, its real id — there is NO name fallback, because a schedule title is free text and one customer often has two schedules (a monthly retainer and an annual licence), so guessing between them would re-bill the wrong contract. proposed holds ONLY what you want changed: title, customerId/customer, lines, cadence, paymentMethod, startDate, endDate, maxOccurrences, notes, and status ("paused" to stop future invoices, "active" to resume). ⚠ lines is WHOLE-REPLACE: send every line the schedule should have, including the unchanged ones — for a price rise, send the same lines with the new prices. ⚠ APPROVING CAN MOVE THE BILLING DATE even when you change only a price: Taokeh re-derives the next issue date from the start date on every save, so the review page states the exact date the next invoice would go out, and whether that has moved. ⛔ WHAT IT CANNOT DO, each refused by name: it cannot set issueMode: "auto" — that would let one approval remove the human tap from every future invoice; it cannot set status: "ended", a ONE-WAY door no later draft could undo (propose "paused" instead, which stops the billing just as completely and can be resumed); it cannot set MFRS 15 revenue spreading, an accounting-policy decision on the schedule's own page; and it cannot touch the invoices this schedule has ALREADY issued — a change reaches the next firing and no earlier one. If a past invoice was wrong, credit it (create_credit_note_draft); the schedule only decides what happens next. A field the record already agrees with is dropped, and a proposal that changes nothing is refused rather than filed as an empty diff. One schedule per call — loop for a sweep across several, because each reviewable diff is the point.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoA SHORT reviewer note, in the reviewer's language: what you changed, why, and what they should double-check.
proposedYesONLY the fields you want changed. A field the record already agrees with is dropped; an unknown or deliberately-excluded field is refused by name.
needsReviewNoSet true when something gave you pause — a price the user was unsure about, a date you inferred.
recurringIdYesThe recurring invoice's real id. Required — there is no name fallback.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only say readOnlyHint=false and destructiveHint=false, which conveys little about safety. The description carries the full burden and excels: it warns nothing changes until human approval, discloses the whole-replace behavior of lines, warns that approving can move the billing date, lists refused operations, and explains that agreeing fields are dropped and empty proposals are refused. This is rich, specific behavioral context beyond any annotation.

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

Conciseness4/5

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

The description is long but every section earns its place: purpose, alternatives, critical warnings, refused operations, and loop guidance. It is front-loaded with the most important constraint (files a draft only). It could be slightly tightened, as some repetition of 'does NOT change anything' appears, but the density of high-value warnings justifies the 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 a complex mutation-adjacent tool with nested objects, no output schema, and no meaningful annotations, the description is thoroughly complete. It covers what happens on approval, what is refused, what the reviewer sees, edge cases like unchanged fields and empty diffs, and how to correct past invoices. An agent has nearly everything needed to call this tool correctly without further research.

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 every parameter. The description adds real semantics: explains that recurringId is required with no name fallback due to free-text titles and multiple schedules per customer, clarifies proposed contains ONLY changed fields, and elaborates on the status enum and lines whole-replace behavior. It does not document every nested subfield in prose, but the schema covers those, so the added semantics beyond schema is strong.

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 leads with a precise verb ('FILES A PENDING DRAFT ONLY') and names the exact resource (a pending recurring-invoice change draft in Taokeh). It distinguishes itself from siblings by clarifying it proposes changes to an ALREADY set up recurring invoice, and contrasts with create_recurring_invoice_draft and create_credit_note_draft. The purpose is unmistakable even without reading 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?

The description gives explicit when-to-use context: propose changes to an existing recurring invoice, including pricing, quantity, end date, cadence, or pausing. It names exclusions and alternatives: cannot set issueMode auto, status ended, MFRS 15, or touch already-issued invoices, and explicitly routes past-invoice errors to create_credit_note_draft. It also states 'One schedule per call — loop for a sweep across several,' giving clear usage boundaries.

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

working_capitalWorking capital (days + who pays slowly)A
Read-only
Inspect

Working capital in DAYS, month by month, plus who is slow to pay — the deterministic answer to "the profit and loss says I made money, so where is the cash?". Give from and to as YYYY-MM, inclusive; the window is capped at 36 months, the same cap financial_timeseries carries. TWO HALVES COME BACK IN ONE CALL. First, months[]: per month revenue, cogs, arClose, apClose, inventoryClose and four ratios — debtorDays (arClose ÷ revenue × days: days of sales sitting unpaid in customers' hands), creditorDays (apClose ÷ cogs × days: days of cost sitting unpaid in yours), inventoryDays (inventoryClose ÷ cogs × days: days of cost sitting on the shelf) and cashConversionCycle (debtorDays + inventoryDays − creditorDays). Every row states days, the calendar days it covers, because a days ratio without its denominator cannot be checked. Second, customers and vendors: per party avgDaysToPay (amount-weighted, from each document's own date to the date the money moved), avgDaysPastDue (the same weighting measured from the due date), invoices, paid and withTerms — slowest first, up to 50 a side with total, shown and more. NULL IS AN ANSWER. A ratio whose denominator is zero comes back null — no comparable base — never 0 and never an enormous number; cashConversionCycle is null whenever any one of its three legs is, and is never the sum of the legs that happen to exist. Relay a null as "there is no base to measure that against", never as zero. ⚠ INVENTORY DAYS IS WITHHELD unless this company runs PERPETUAL costing. On Taokeh's default mode (modified periodic) a sale does not move stock and cost of goods sold is recognised only at a stock take, so the inventory balance sits still and then jumps while monthly COGS is zero in most months — a monthly inventory-days figure on that basis would measure something else. inventoryClose is still returned, because it is a real ledger balance; inventoryDays and cashConversionCycle are null and a note says why. Do NOT compute it yourself from inventoryClose and cogs: that is precisely the number the server declined to state. WHAT PAYMENT SPEED EXCLUDES, and say so when you relay it: cash sales and cash bills (they settle on their own date and would average zeros into every party), opening invoices and opening bills (those dates belong to the old system, not to this company's paper), refunds (a negative allocation is money walking back out, not a customer paying) and contra set-offs (a set-off moves no bank money). MONTHS THAT DO NOT EXIST ARE ABSENT, NOT ZERO: months ending before this company's accounting start date, and months after today. A month still running is partial: true with through = today, and its days counts only the days that have happened, so both sides of every division are month-to-date — say so, and never let that row bend a trend. The cutover month is partial with startsAt, and its days, revenue and cogs all count from there — so its revenue can be lower than financial_timeseries shows for the same month, which runs from the 1st. EQUAL BASIS: revenue and cogs are the /reports income statement, arClose and apClose the A/R and A/P aging reports' own totals as of month end, inventoryClose the ledger balance of the mapped inventory account. Nothing is re-summed, and basis states every formula with its exact inputs. DRILL DOWN RATHER THAN GUESS: a slow customer here → ar_aging for the buckets, open_invoices for that customer's unpaid documents, search_documents with docType 'payment' for the settlements behind the average, get_document_pdf for the paper itself. FIGURES ONLY — no verdict, no benchmark, no trend label, no "healthy" and no "improving". The reading is yours to write. A very wide window can exceed this call's time budget, in which case it is REFUSED (naming how far it got) rather than answered with a short series. Nothing is written.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYes
fromYes

TDQS

A4.8/5.0
Behavior5/5

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

Annotations provide only readOnlyHint and openWorldHint, so the description carries the full behavioral burden — and discharges it thoroughly. It discloses null-is-an-answer semantics (zero denominators never become 0), the perpetual-costing withholding with rationale, what payment speed excludes (cash sales, opening invoices, refunds, contra set-offs), absent-vs-zero months, partial/cutover month math, the exact data basis, and refusal on oversized windows. The closing 'Nothing is written' is consistent with readOnlyHint; no contradiction.

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

Conciseness4/5

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

The description is long, but every capitalized block — NULL, INVENTORY DAYS, WHAT PAYMENT SPEED EXCLUDES, MONTHS, EQUAL BASIs, DRIL DOWN, FIGURES ONLY — carries distinct operational knowledge an agent would otherwise mis-relay. It is front-loaded with the purpose line and scannable via headers; some tightening was possible, but nothing reads as 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 alone must specify the return shape — it does, down to field names (arClose, apClose, inventoryClose), ratio formulas with their denominators, customer/vendor aggregates, and the basis of every figure. Edge-case handling (nulls, partial months, cutover, refusal) and drill-down routing are all present, so an agent can call, parse, and relay 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 0%, so the description must compensate; it adds that from/to are 'YYYY-MM, inclusive' and that the window caps at 36 months, matching financial_timeseries. The format itself is already in the schema pattern, so the marginal contribution is the inclusivity rule and cap. Month-existence semantics (business start date, after today) are covered elsewhere in the body, making this adequate but not exhaustive.

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 deliverable — 'Working capital in DAYS, month by month, plus who is slow to pay' — and frames it against a concrete business question ('the profit and loss says I made money, so where is the cash?'). The 'deterministic answer' framing marks the scope as calculation, not judgment, and the return structure (months[] plus customers/vendors) is clearly announced.

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 names the drill-down chain for follow-up: a slow customer here → ar_aging, open_invoices, search_documents with docType 'payment', get_document_pdf. It also states when-not: inventory days are withheld under periodic costing and 'Do NOT compute it yourself from inventoryClose and cogs', plus the wide-window refusal. The 36-month cap is tied to a sibling (financial_timeseries), giving the agent an anchor across tools.

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. Dates show when Glama detected each change.

  1. 13 tool updates
    • Changedcreate_bill_draft2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the supplier's document, when it says more than the product name does — a size, a grade, a pack, a period covered. It rides onto the posted line, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
    • Changedcreate_credit_note_draft2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the document, when it says more than the product name does — a size, a grade, a job reference, a period covered. It rides onto the posted line and prints on the customer's copy, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
    • Changedcreate_debit_note_draft1 field changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
    • Changedcreate_invoice_draft2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the document, when it says more than the product name does — a size, a grade, a job reference, a period covered. It rides onto the posted line and prints on the customer's copy, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
    • Changedcreate_journal_draft2 fields changed
      • changedInput schema / properties / lines / description
        Previous value: -"At least two lines. The debits must equal the credits TO THE SEN — an unbalanced entry is refused with the difference named."New value: +"At least two lines. The debits must equal the credits TO THE SEN — an unbalanced entry is refused with the difference named. ⛔ LINE KEYS ARE STRICT: a key this schema does not list is REFUSED BY NAME and NOTHING is filed."
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
    • Changedcreate_purchase_order_draft2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the supplier's document, when it says more than the product name does — a size, a grade, a pack, a period covered. It rides onto the posted line, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
    • Changedcreate_quote_draft2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the document, when it says more than the product name does — a size, a grade, a job reference, a period covered. It rides onto the posted line and prints on the customer's copy, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
    • Changedcreate_recurring_invoice_draft2 fields changed
      • changedInput schema / properties / lines / description
        Previous value: -"What gets billed every cycle. Every line must be a real catalogue product."New value: +"What gets billed every cycle. Every line must be a real catalogue product. ⛔ LINE KEYS ARE STRICT: a key this schema does not list is REFUSED BY NAME and NOTHING is filed."
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
    • Changedstage_document2 fields changed
      • addedInput schema / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the historical document, when it says more than the product name does — a size, a grade, a job reference. It rides onto the posted line and is what the owner reads beside the original. THIS IS ALSO WHERE A NON-STOCK LINE LIVES: a delivery charge, a transport fee or a labour line has no catalogued product, so put its own wording in `productRef` (it is required and must not be blank) and any extra detail here — the line stages, is flagged as unresolved, and the owner picks or creates the item on the review screen. Do NOT drop the line and do not fold it into another one."
    • Changedstage_master_data1 field changed
      • addedInput schema / properties / rows / items / additionalProperties
        Added value: +false
    • Changedstage_opening_balances1 field changed
      • addedInput schema / properties / rows / items / additionalProperties
        Added value: +false
    • Changedupdate_invoice_draft4 fields changed
      • changedInput schema / properties / proposed / properties / lines / description
        Previous value: -"The FULL replacement line set — every line the corrected invoice should have, not only the one that was wrong. Same shape as create_invoice_draft. Omit it entirely when you are only correcting header fields."New value: +"The FULL replacement line set — every line the corrected invoice should have, not only the one that was wrong. Same shape as create_invoice_draft. Omit it entirely when you are only correcting header fields. ⛔ LINE KEYS ARE STRICT, exactly as on create_invoice_draft: a key this schema does not list is REFUSED BY NAME and NOTHING is filed — the EDIT door and the CREATE door judge a line the same way (memory: erp-draft-lane-shared-rules)."
      • addedInput schema / properties / proposed / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / proposed / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the document, when it says more than the product name does — a size, a grade, a job reference, a period covered. It rides onto the posted line and prints on the customer's copy, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
      • addedInput schema / properties / proposed / properties / lines / minItems
        Added value: +1
    • Changedupdate_recurring_invoice_draft4 fields changed
      • changedInput schema / properties / proposed / properties / lines / description
        Previous value: -"WHOLE-REPLACE. Send every line the schedule should bill from now on, not just the changed ones — a partial set would silently drop the rest."New value: +"WHOLE-REPLACE. Send every line the schedule should bill from now on, not just the changed ones — a partial set would silently drop the rest. ⛔ LINE KEYS ARE STRICT, exactly as on create_recurring_invoice_draft: a key this schema does not list is REFUSED BY NAME and NOTHING is filed."
      • addedInput schema / properties / proposed / properties / lines / items / additionalProperties
        Added value: +false
      • addedInput schema / properties / proposed / properties / lines / items / properties / description / description
        Added value: +"The line text as PRINTED on the document, when it says more than the product name does — a size, a grade, a job reference, a period covered. It rides onto the posted line and prints on the customer's copy, so send what the paper says rather than a tidier phrasing of your own. Leave it out when the product name already says it. This is TEXT, not a field: Taokeh has no column for a dimension, a grade or a variant, so anything of that kind belongs here."
      • addedInput schema / properties / proposed / properties / lines / minItems
        Added value: +1
  2. 1 tool update
    • Addedworking_capital
  3. 3 tool updates
    • Changedcreate_bill_draft2 fields changed
      • addedInput schema / properties / dueDate
        Added value: +{
        +  "description": "The due date, YYYY-MM-DD, when the bill states one outright. You usually do not need it: for one of the five preset terms above, Taokeh fills the due date on the draft itself (bill date + 0/7/14/30/60 days) and shows it on the approval screen for the owner to check. State dueDate only to override that, or when the paper gives a due date that does not follow the term. A term Taokeh does not recognise fills NOTHING — if that bill has a due date, say it here, because otherwise the bill falls due on its own date and shows up in the payables aging and the cash forecast a whole credit period early.",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / term
        Added value: +{
        +  "description": "The SUPPLIER's payment term, exactly as the bill prints it ('Due on Receipt', 'Net 7', 'Net 14', 'Net 30', 'Net 60', or whatever this supplier actually stated — 'COD 7 days', 'Net 45', '30 days EOM'). It is stored as written, so do NOT round a real term to the nearest familiar one. Leave it out when the bill states no term: an unstated term is not 'Due on Receipt', and the bill then simply falls due on its own date.",
        +  "maxLength": 100,
        +  "type": "string"
        +}
    • Changedrevise_draft2 fields changed
      • changedInput schema / properties / patch / properties / dueDate / description
        Previous value: -"invoice: the due date, YYYY-MM-DD, to state or correct one outright. Pass '' to drop your stated date and fall back to what the term derives (nothing, on a term Taokeh does not recognise — that invoice then posts due on its own issue date)."New value: +"invoice / bill: the due date, YYYY-MM-DD, to state or correct one outright. Pass '' to drop your stated date and fall back to what the term derives (nothing, on a term Taokeh does not recognise — that document then falls due on its own issue date)."
      • changedInput schema / properties / patch / properties / term / description
        Previous value: -"invoice / quote / purchase_order: the payment/delivery term line. On an invoice, the term as the paper states it — pass '' to clear it. Changing it to a PRESET term ('Due on Receipt', 'Net 7/14/30/60') also re-fills a due date Taokeh derived; a due date you stated yourself is left alone."New value: +"invoice / bill / quote / purchase_order: the payment/delivery term line. On an invoice, the term as the paper states it; on a BILL, the term the SUPPLIER printed — pass '' to clear it on either. Changing it to a PRESET term ('Due on Receipt', 'Net 7/14/30/60') also re-fills a due date Taokeh derived; a due date you stated yourself is left alone."
    • Changedsearch_documents2 fields changed
      • changedInput schema / properties / dueFrom / description
        Previous value: -"Earliest DUE date (YYYY-MM-DD) — this is the \"what's due this week\" filter, and it asks about when the money falls due, not when the invoice was raised (that's `from`/`to`). INVOICES ONLY: pass docType:'invoice' with it, or the call is refused, because nothing else in this search has a due date and quietly dropping every quote and bill would be a wrong answer wearing a right one's clothes."New value: +"Earliest DUE date (YYYY-MM-DD) — this is the \"what's due this week\" filter, and it asks about when the money falls due, not when the document was raised (that's `from`/`to`). INVOICES OR BILLS, one at a time: pass docType:'invoice' (money coming in) or docType:'bill' (money going out) with it, or the call is refused. Nothing else in this search has a due date, and quietly dropping every quote and delivery order would be a wrong answer wearing a right one's clothes; netting receivables and payables into one list would be another."
      • changedInput schema / properties / dueTo / description
        Previous value: -"Latest DUE date (YYYY-MM-DD). Same invoices-only rule as dueFrom. Pair the two for a window — dueFrom + dueTo across this week answers \"what's landing on me before Friday\"; dueTo alone with a past date is everything already due."New value: +"Latest DUE date (YYYY-MM-DD). Same docType rule as dueFrom — 'invoice' or 'bill'. Pair the two for a window: dueFrom + dueTo across this week with docType:'bill' answers \"what do I owe before Friday\"; dueTo alone with a past date is everything already due."
  4. 1 tool update
    • Changedcreate_payment_draft2 fields changed
      • changedInput schema / properties / allocations / description
        Previous value: -"The explicit per-bill split. Each amount is capped at that bill’s live outstanding by the server."New value: +"The explicit per-bill split, at most 50 lines. Each amount is capped at that bill’s live outstanding by the server."
      • addedInput schema / properties / allocations / maxItems
        Added value: +50
  5. 1 tool update
    • Addedfinancial_timeseries
  6. 2 tool updates
    • Changedbank_review_queue3 fields changed
      • addedInput schema / properties / from
        Added value: +{
        +  "description": "Earliest transaction date (YYYY-MM-DD). WITHOUT a statementId, from/to widen the read to a DATE WINDOW across every imported statement — 'what did the bank register show in July' rather than 'what is on this one statement'.",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
      • addedInput schema / properties / status
        Added value: +{
        +  "description": "Which rows: 'unreviewed' (DEFAULT — everything not yet posted or ignored, i.e. the review queue), 'confirmed', 'posted', 'ignored', or 'all'. Only unreviewed rows carry suggestions; the rest carry what was decided.",
        +  "type": "string"
        +}
      • addedInput schema / properties / to
        Added value: +{
        +  "description": "Latest transaction date (YYYY-MM-DD).",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
    • Changedsearch_documents1 field changed
      • changedInput schema / properties / docType / description
        Previous value: -"Restrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order'. Omit for all. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill."New value: +"Restrict to one type: 'invoice','credit_note','sales_debit_note','quote','delivery_order','bill','debit_note','purchase_order','payment'. Omit for all — EXCEPT 'payment', which is opt-in only and is never returned unless you name it. NOTE the two debit notes: 'sales_debit_note' is one this business ISSUED to a customer (additional charges on an invoice — money owed TO this business); 'debit_note' is the BUY side, issued to a supplier against a bill."
  7. 4 tool updates
    • Addedcreate_payment_draft
    • Changedget_attachment2 fields changed
      • changedInput schema / properties / owner / description
        Previous value: -"What the original hangs off: 'expense' = a POSTED paid expense (use the expenseId from search_expenses); 'expense_draft' / 'invoice_draft' / 'bill_draft' / 'quote_draft' / 'receipt_draft' / 'contact_draft' = a PENDING draft (use its draftId); 'shoebox' = a photo someone in the business sent in from their phone and nobody has read yet (use the id from shoebox_items)."New value: +"What the original hangs off: 'expense' = a POSTED paid expense (use the expenseId from search_expenses); 'expense_draft' / 'invoice_draft' / 'bill_draft' / 'quote_draft' / 'receipt_draft' / 'payment_draft' / 'contact_draft' = a PENDING draft (use its draftId); 'shoebox' = a photo someone in the business sent in from their phone and nobody has read yet (use the id from shoebox_items)."
      • changedInput schema / properties / owner / enum
        Previous value: -[
        -  "expense",
        -  "invoice",
        -  "credit_note",
        -  "bill",
        -  "quote",
        -  "expense_draft",
        -  "invoice_draft",
        -  "bill_draft",
        -  "quote_draft",
        -  "receipt_draft",
        -  "contact_draft",
        -  "journal_draft",
        -  "shoebox"
        -]New value: +[
        +  "expense",
        +  "invoice",
        +  "credit_note",
        +  "bill",
        +  "quote",
        +  "expense_draft",
        +  "invoice_draft",
        +  "bill_draft",
        +  "quote_draft",
        +  "receipt_draft",
        +  "payment_draft",
        +  "contact_draft",
        +  "journal_draft",
        +  "shoebox"
        +]
    • Changedmy_work1 field changed
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "expense",
        -  "invoice",
        -  "bill",
        -  "quote",
        -  "receipt",
        -  "contact",
        -  "contact_update",
        -  "employee_update",
        -  "product_update",
        -  "recurring",
        -  "credit_note",
        -  "debit_note",
        -  "purchase_order",
        -  "journal",
        -  "invoice_update",
        -  "logo_update",
        -  "bank",
        -  "staged_documents",
        -  "staged_balances",
        -  "staged_master"
        -]New value: +[
        +  "expense",
        +  "invoice",
        +  "bill",
        +  "quote",
        +  "receipt",
        +  "payment",
        +  "contact",
        +  "contact_update",
        +  "employee_update",
        +  "product_update",
        +  "recurring",
        +  "credit_note",
        +  "debit_note",
        +  "purchase_order",
        +  "journal",
        +  "invoice_update",
        +  "logo_update",
        +  "bank",
        +  "staged_documents",
        +  "staged_balances",
        +  "staged_master"
        +]
    • Changedrevise_draft8 fields changed
      • changedInput schema / properties / kind / enum
        Previous value: -[
        -  "expense",
        -  "invoice",
        -  "bill",
        -  "quote",
        -  "receipt",
        -  "contact",
        -  "contact_update",
        -  "employee_update",
        -  "product_update",
        -  "recurring",
        -  "credit_note",
        -  "sales_debit_note",
        -  "purchase_order",
        -  "journal",
        -  "invoice_update"
        -]New value: +[
        +  "expense",
        +  "invoice",
        +  "bill",
        +  "quote",
        +  "receipt",
        +  "payment",
        +  "contact",
        +  "contact_update",
        +  "employee_update",
        +  "product_update",
        +  "recurring",
        +  "credit_note",
        +  "sales_debit_note",
        +  "purchase_order",
        +  "journal",
        +  "invoice_update"
        +]
      • changedInput schema / properties / patch / properties / allocations / description
        Previous value: -"receipt: the REPLACEMENT per-invoice split. Re-clamped against the customer's LIVE open invoices."New value: +"receipt: the REPLACEMENT per-invoice split (saleId or reference), re-clamped against the customer's LIVE open invoices. payment: the REPLACEMENT per-bill split (purchaseId or reference), re-clamped against the supplier's LIVE open bills."
      • addedInput schema / properties / patch / properties / allocations / items / properties / purchaseId
        Added value: +{
        +  "type": "string"
        +}
      • changedInput schema / properties / patch / properties / bankAccountId / description
        Previous value: -"receipt: the suggested receiving bank/cash account; null clears the suggestion."New value: +"receipt: the suggested receiving bank/cash account. payment: the suggested PAYING bank/cash account (never a credit card). null clears the suggestion."
      • addedInput schema / properties / patch / properties / paymentDate
        Added value: +{
        +  "description": "payment: the date the money left the account.",
        +  "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
        +  "type": "string"
        +}
      • changedInput schema / properties / patch / properties / total / description
        Previous value: -"receipt: a lump sum to re-auto-allocate oldest-first across the open invoices (instead of allocations)."New value: +"receipt / payment: a lump sum to re-auto-allocate oldest-first across the open invoices / bills (instead of allocations)."
      • changedInput schema / properties / patch / properties / vendor / description
        Previous value: -"bill / purchase_order: the supplier name to re-resolve."New value: +"bill / purchase_order / payment: the supplier name to re-resolve."
      • changedInput schema / properties / patch / properties / vendorId / description
        Previous value: -"bill / purchase_order: the resolved vendor id."New value: +"bill / purchase_order / payment: the resolved vendor id."
  8. 1 tool update
    • Changeddraft_bank_classification1 field changed
      • addedInput schema / properties / suggestions / items / properties / allocations
        Added value: +{
        +  "items": {
        +    "properties": {
        +      "amount": {
        +        "exclusiveMinimum": 0,
        +        "type": "number"
        +      },
        +      "docNumber": {
        +        "maxLength": 60,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "docNumber",
        +      "amount"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 20,
        +  "minItems": 1,
        +  "type": "array"
        +}
  9. 7 tool updates
    • Changedcreate_bill_draft2 fields changed
      • changedInput schema / properties / lines / items / properties / quantity / description
        Previous value: -"The line quantity. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."New value: +"The line quantity. On a measurement-profile company (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough company nothing is derived, so this IS the quantity — send it."
      • changedInput schema / properties / lines / items / properties / thickness / description
        Previous value: -"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."New value: +"Thickness in inches on a dimensional line — measurement-profile companies only (intake_contract shows this company's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
    • Changedcreate_invoice_draft2 fields changed
      • changedInput schema / properties / lines / items / properties / quantity / description
        Previous value: -"The line quantity. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."New value: +"The line quantity. On a measurement-profile company (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough company nothing is derived, so this IS the quantity — send it."
      • changedInput schema / properties / lines / items / properties / thickness / description
        Previous value: -"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."New value: +"Thickness in inches on a dimensional line — measurement-profile companies only (intake_contract shows this company's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
    • Changedcreate_purchase_order_draft2 fields changed
      • changedInput schema / properties / lines / items / properties / quantity / description
        Previous value: -"The line quantity. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."New value: +"The line quantity. On a measurement-profile company (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough company nothing is derived, so this IS the quantity — send it."
      • changedInput schema / properties / lines / items / properties / thickness / description
        Previous value: -"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."New value: +"Thickness in inches on a dimensional line — measurement-profile companies only (intake_contract shows this company's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
    • Changedcreate_quote_draft2 fields changed
      • changedInput schema / properties / lines / items / properties / quantity / description
        Previous value: -"The line quantity. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."New value: +"The line quantity. On a measurement-profile company (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the reviewer beside the server's. On the default passthrough company nothing is derived, so this IS the quantity — send it."
      • changedInput schema / properties / lines / items / properties / thickness / description
        Previous value: -"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."New value: +"Thickness in inches on a dimensional line — measurement-profile companies only (intake_contract shows this company's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
    • Changedstage_document2 fields changed
      • changedInput schema / properties / lines / items / properties / quantity / description
        Previous value: -"The line quantity as the old document states it. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the owner beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."New value: +"The line quantity as the old document states it. On a measurement-profile company (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the owner beside the server's. On the default passthrough company nothing is derived, so this IS the quantity — send it."
      • changedInput schema / properties / lines / items / properties / thickness / description
        Previous value: -"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."New value: +"Thickness in inches on a dimensional line — measurement-profile companies only (intake_contract shows this company's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
    • Changedstock_movements1 field changed
      • changedInput schema / properties / sourceType / description
        Previous value: -"Exactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual workspace."New value: +"Exactly one movement cause. One of: purchase, purchase_void, debit_note, debit_note_void, adjustment, stock_take, import_opening, assembly_out, assembly_in, disassembly_out, disassembly_in, sale, sale_void, credit_note, transfer_out, transfer_in. Note that sale, sale_void, credit_note only ever exist in a perpetual company."
    • Changedupdate_invoice_draft1 field changed
      • changedInput schema / properties / proposed / properties / lines / items / properties / quantity / description
        Previous value: -"The corrected line quantity. On a measurement-profile workspace OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity, and a quantity sent alongside a parseable tally is kept as advisory only, never used to compute."New value: +"The corrected line quantity. On a measurement-profile company OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity, and a quantity sent alongside a parseable tally is kept as advisory only, never used to compute."
  10. 1 tool update
    • Changedstage_document4 fields changed
      • addedInput schema / properties / lines / items / properties / quantity / description
        Added value: +"The line quantity as the old document states it. On a measurement-profile workspace (see intake_contract's `measureProfile`) OMIT it whenever you give thickness/width/tally, or write the measure detail into the description ('2x2 = 10/10 12/14') — the server derives the authoritative quantity from those, and a quantity sent alongside a parseable tally is NOT used to compute: it is kept as your advisory figure and shown to the owner beside the server's. On the default passthrough workspace nothing is derived, so this IS the quantity — send it."
      • addedInput schema / properties / lines / items / properties / tally / description
        Added value: +"The piece tally as pieces/length_ft pairs — '10/10 12/14' is 10 pieces of 10 ft and 12 of 14 ft. With thickness and width this is what the quantity is derived FROM."
      • addedInput schema / properties / lines / items / properties / thickness / description
        Added value: +"Thickness in inches on a dimensional line — measurement-profile workspaces only (intake_contract shows this workspace's `measureProfile`). Give thickness + width + tally INSTEAD of a quantity and the server computes the authoritative quantity from them."
      • addedInput schema / properties / lines / items / properties / width / description
        Added value: +"Width in inches on a dimensional line. Goes with thickness and tally."
  11. 3 tool updates
    • Changedcreate_journal_draft1 field changed
      • changedInput schema / properties / lines / items / properties / accountRef / description
        Previous value: -"The account CODE from this workspace's chart (best), or its EXACT name. Never a description and never a guess — an unknown ref is refused, and this tool never creates an account."New value: +"The account CODE from this company's chart (best), or its EXACT name. Never a description and never a guess — an unknown ref is refused, and this tool never creates an account."
    • Changedstage_document2 fields changed
      • changedInput schema / properties / docKind / description
        Previous value: -"'sales_invoice' = an invoice this workspace ISSUED to a customer. 'purchase_bill' = a bill a supplier issued TO this workspace (inventory lines only, same rule as create_bill_draft). Other kinds are not supported yet."New value: +"'sales_invoice' = an invoice this company ISSUED to a customer. 'purchase_bill' = a bill a supplier issued TO this company (inventory lines only, same rule as create_bill_draft). Other kinds are not supported yet."
      • changedInput schema / properties / reference / description
        Previous value: -"The document number exactly as printed in the old system (e.g. INV1603). Taokeh keeps it, so the customer's copy and yours still match. It must be unique in this workspace: a number already on the books is refused by name. Leave it out only if the document genuinely has no number. Before the first such invoice is entered, the owner must confirm where the real invoice series continues; Taokeh never silently starts migrated books at INV1."New value: +"The document number exactly as printed in the old system (e.g. INV1603). Taokeh keeps it, so the customer's copy and yours still match. It must be unique in this company: a number already on the books is refused by name. Leave it out only if the document genuinely has no number. Before the first such invoice is entered, the owner must confirm where the real invoice series continues; Taokeh never silently starts migrated books at INV1."
    • Changedstage_master_data5 fields changed
      • changedInput schema / properties / kind / description
        Previous value: -"'products' = the item list / catalogue. 'contacts' = the customer and supplier book. 'accounts' = the chart of accounts. 'settings' = the workspace setup; its complete stageable and owner-only classification is returned by intake_contract(doc_type:'settings'). 'employees' = the staff list; admin-only and create-only."New value: +"'products' = the item list / catalogue. 'contacts' = the customer and supplier book. 'accounts' = the chart of accounts. 'settings' = the company setup; its complete stageable and owner-only classification is returned by intake_contract(doc_type:'settings'). 'employees' = the staff list; admin-only and create-only."
      • changedInput schema / properties / rows / items / properties / isCustomer / description
        Previous value: -"contacts: true when this party BUYS from the workspace. A party can be both; both flags true creates the record on each side, which is how the receivable and the payable stay separate."New value: +"contacts: true when this party BUYS from you. A party can be both; both flags true creates the record on each side, which is how the receivable and the payable stay separate."
      • changedInput schema / properties / rows / items / properties / isVendor / description
        Previous value: -"contacts: true when this party SELLS to the workspace. A row that states NEITHER flag and has no set-level defaultRole is skipped at import — Taokeh names those rows back to you."New value: +"contacts: true when this party SELLS to you. A row that states NEITHER flag and has no set-level defaultRole is skipped at import — Taokeh names those rows back to you."
      • changedInput schema / properties / rows / items / properties / settingValue / description
        Previous value: -"settings: the value to store, as a string. Send only what the owner told you or what the old system's records print — an inferred TIN or registration number passes this import and fails at LHDN months later. locale is 'en' or 'ms'; measure.divisor is a NUMBER (the timber trade-ton divisor is 7200, a 50 ft³ ton, not a cubic metre); accounting.opening_date is YYYY-MM-DD and is refused if this workspace already has posted entries dated before it. A row with no value is refused rather than applied — clearing a setting is the owner's own act on its page."New value: +"settings: the value to store, as a string. Send only what the owner told you or what the old system's records print — an inferred TIN or registration number passes this import and fails at LHDN months later. locale is 'en' or 'ms'; measure.divisor is a NUMBER (the timber trade-ton divisor is 7200, a 50 ft³ ton, not a cubic metre); accounting.opening_date is YYYY-MM-DD and is refused if this company already has posted entries dated before it. A row with no value is refused rather than applied — clearing a setting is the owner's own act on its page."
      • changedInput schema / properties / rows / items / properties / sku / description
        Previous value: -"products: the item code, unique per workspace. THE KEY — an existing SKU is UPDATED, a new one is created. Required for a product row."New value: +"products: the item code, unique per company. THE KEY — an existing SKU is UPDATED, a new one is created. Required for a product row."
  12. 1 tool update
    • Addedstock_movements
  13. 1 tool update
    • Addedsearch_document_lines
  14. 4 tool updates
    • Changedfind_in_taokeh1 field changed
      • addedInput schema / properties / query / description
        Added value: +"What the user wants to DO or the setting they want to CHANGE, in words — not a document number, a customer name or an amount (those are records; use search_documents / resolve_customer instead)."
    • Changedsearch_documents8 fields changed
      • addedInput schema / properties / customer
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
        +}
      • addedInput schema / properties / docNumber
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the document number as `number` (partial matches are fine)."
        +}
      • addedInput schema / properties / ref
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
        +}
      • addedInput schema / properties / refNo
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
        +}
      • addedInput schema / properties / reference
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the customer's own Ref No (their DO / PO number) as `number` — that one parameter searches BOTH the invoice's own number and the customer's Ref No, and the row it returns reports each separately as `number` and `refNo`."
        +}
      • addedInput schema / properties / supplier
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
        +}
      • addedInput schema / properties / text
        Added value: +{
        +  "description": "NOT a filter on this tool. This search matches document numbers and party names only — use `number` or `party`. To search memo/line text, use search_journal (`text`) or search_expenses (`text`)."
        +}
      • addedInput schema / properties / vendor
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass a customer or vendor name as `party`."
        +}
    • Changedsearch_expenses9 fields changed
      • addedInput schema / properties / account
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the chart-of-accounts code as `accountCode` (exact)."
        +}
      • addedInput schema / properties / category
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the category by its chart-of-accounts code as `accountCode` (exact) — get codes from expense_accounts."
        +}
      • addedInput schema / properties / description
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass memo text as `text`."
        +}
      • addedInput schema / properties / memo
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass memo text as `text`."
        +}
      • addedInput schema / properties / number
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the supplier/receipt reference as `reference` — a posted expense has no document number of its own."
        +}
      • addedInput schema / properties / ref
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the supplier/receipt reference as `reference`."
        +}
      • addedInput schema / properties / refNo
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the supplier/receipt reference as `reference`."
        +}
      • addedInput schema / properties / supplier
        Added value: +{
        +  "description": "NOT a filter on this tool. A posted expense carries no party field here — search the supplier name as `text` (it matches the memo/description) or as `reference`."
        +}
      • addedInput schema / properties / vendor
        Added value: +{
        +  "description": "NOT a filter on this tool. A posted expense carries no party field here — search the supplier name as `text` (it matches the memo/description) or as `reference`."
        +}
    • Changedsearch_journal8 fields changed
      • addedInput schema / properties / account
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the chart-of-accounts code as `accountCode` (exact)."
        +}
      • addedInput schema / properties / description
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass the text as `text` (it matches the entry memo AND every line description)."
        +}
      • addedInput schema / properties / memo
        Added value: +{
        +  "description": "NOT a filter on this tool. Pass memo text as `text` (it matches the entry memo AND every line description)."
        +}
      • addedInput schema / properties / number
        Added value: +{
        +  "description": "NOT a filter on this tool. A journal entry has no document number — search its memo and line descriptions with `text`, or find the document itself with search_documents."
        +}
      • addedInput schema / properties / party
        Added value: +{
        +  "description": "NOT a filter on this tool. The ledger has no party column — search the name as `text`, or find the document with search_documents."
        +}
      • addedInput schema / properties / ref
        Added value: +{
        +  "description": "NOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`."
        +}
      • addedInput schema / properties / refNo
        Added value: +{
        +  "description": "NOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`."
        +}
      • addedInput schema / properties / reference
        Added value: +{
        +  "description": "NOT a filter on this tool. A journal entry has no reference field — search its memo and line descriptions with `text`."
        +}

Frequently Asked Questions

Discussions

No comments yet. Be the first to start the discussion!

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    Enables AI assistants to query and manage self-hosted accounting data—invoices, balances, and books—through natural language, with read-only tools by default and optional scoped write operations.
    10
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Gives AI models native-level control over TallyPrime ERP, covering 169+ tools across all functional modules including masters, vouchers, reports, GST, payroll, and more.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to read and write Cynco accounting data, including querying books, creating invoices, reconciling transactions, and generating financial reports.
    7
    1
    MIT
  • F
    license
    B
    quality
    B
    maintenance
    Connects AI assistants to Big Red Cloud accounting data, enabling read-only lookups and safe write operations with confirmation drafts.
    100
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources