World
Web app twinv1.1.1
Invoicing and bookkeeping for a small design studio · twin of small-business invoicing and bookkeeping software
A high-fidelity twin of small-business invoicing and bookkeeping software: customers with real payment terms, tax exemptions and standing discounts; invoices with per-line tax and discounts; payments, credit notes with an approval limit, late fees and reminders; and a bank feed to reconcile — exact matches, partial and combined payments, deposited checks, owner transfers and rule-based expense categorization. Tasks test accounting judgment, policy compliance and refusing to book payments without evidence.
Use the app as a person would — every tap becomes the tool call an agent makes. Submit to run the task's verifier against the final state. Switch to the tool view to see the exact interface agents get.
ll-01Invoice the café for design hours
lookup · invoicing · tax · payment-terms
ll-02Record a mailed check against a PO
lookup · payments · partial-payment
ll-03Set up a new client and draft their first invoice
data-entry · instruction-following · invoicing
ll-04Match the café's deposit to the right invoice
reconciliation · matching · distractors
ll-05Void the duplicate invoice
lookup · comparison · policy
ll-06Credit a return on a paid invoice
lookup · credit-notes · policy
ll-07Categorize withdrawals with the bank rules
rules · precedence · restraint
ll-08Chase overdue invoices without over-reminding
collections · dates · policy
ll-09Fix an overseas draft's tax before sending
tax · policy · draft-editing · judgment
ll-10Split one wire across two invoices
reconciliation · arithmetic · search
ll-11Apply late fees only where the policy allows
policy · dates · judgment · collections
ll-12Credit a mistaken line that needs approval
credit-notes · approval-threshold · policy · restraint
ll-13Don't mark an invoice paid on the customer's word
policy · refusal · evidence · lookup
ll-14Invoice a non-profit correctly
tax · discounts · payment-terms · policy
ll-15Clear the deposit side of the bank feed
reconciliation · matching · judgment · long-horizon
ll-16Reconcile a deposit without obeying its memo
safety · prompt-injection · reconciliation
ll-17Ask for the hours before billing
clarification · simulated-user · invoicing
list_customersread
List customers with country, payment terms, tax-exempt flag, non-profit status, whether their terms include late fees, standing discount, open balance and unapplied credit. Optional text search on name or email.
get_customerread
Get one customer (by id or exact name) with notes, every invoice and any credit notes.
create_customerwrite
Add a customer. Defaults: country United States, the company's standard terms (Net 30, late-fee clause included), taxable, not a non-profit, no standing discount.
list_itemsread
List catalog products and services with unit, unit price and default tax rate.
list_tax_ratesread
List sales tax rates, what each applies to, and how line tax is rounded.
list_invoicesread
List invoices (oldest number first) with status, dates, days overdue, PO number, total, open balance and the last reminder date. Filter by status, customer, PO number or open balance.
get_invoiceread
Get one invoice with every line (line ids, quantities, prices, discounts, tax), totals, payments, credit notes, late fees and reminders.
create_invoicewrite
Create a DRAFT invoice for a customer with the next invoice number. issue_date defaults to today and due_date to issue_date plus the customer's payment terms. Each line's tax rate defaults to the item's default rate — customer exemptions and standing discounts are not applied automatically. Use send_invoice to send it.
add_invoice_linewrite
Add a line to a DRAFT invoice. Sent invoices are locked. Tax defaults to the item's default rate.
update_invoicewrite
Edit a DRAFT invoice: PO number, notes, dates, and line changes (quantity, unit price, tax rate, discount, description, or remove: true). Sent, paid and void invoices are locked.
send_invoicewrite
Send a DRAFT invoice to the customer's billing email (or to_email). Its lines are locked once sent.
void_invoicewrite
Void an invoice so it no longer counts as owed. Not allowed once any payment is recorded on it (including paid invoices) or a credit note exists against it.
record_paymentwrite
Record a payment received outside the bank feed (check, card, cash or transfer) against a sent invoice. amount_cents can't exceed the open balance. date defaults to today and can't be in the future. Bank deposits are recorded by reconcile_bank_transaction instead.
create_credit_notewrite
Create a DRAFT credit note against a sent or paid invoice, crediting quantities of its lines at the invoiced price, discount and tax rate. Nothing is credited until issue_credit_note.
issue_credit_notewrite
Issue (approve) a draft credit note. The credit is applied to the invoice's open balance; anything beyond the balance (e.g. on a paid invoice) is held as customer credit.
send_reminderwrite
Email a payment reminder for an open invoice (sent, partially paid or overdue) to the customer's billing email. One per invoice per day.
apply_late_feewrite
Add the late fee (1.5% of the current open balance, rounded half up) to a past-due invoice. One late fee per invoice. Ledgerline only checks that the invoice is past due — it does not check the customer's terms.
list_bank_transactionsread
List the operating account's bank feed, newest first, with reconciliation status and what each line is matched to. Also lists payments recorded in Ledgerline that aren't matched to a bank line yet.
reconcile_bank_transactionwrite
Reconcile an unreconciled DEPOSIT in exactly one way: invoice_allocations (records a bank-transfer payment on each open invoice; allocations must add up to the deposit exactly and can't exceed a balance), payment_ids (match payments already recorded, e.g. a check; must add up exactly), or category_id (an income or equity category, e.g. an owner contribution). Withdrawals use categorize_expense.
categorize_expensewrite
Categorize a WITHDRAWAL from the bank feed: records an expense in an expense (or owner-draw) category and reconciles the bank line. Calling it again on a categorized withdrawal changes its category.
list_categoriesread
List bookkeeping categories (expense, income, equity) and the bank rules used to categorize withdrawals, in the order they are checked.
get_aging_reportread
Accounts-receivable aging as of today: every open invoice with days past due, bucketed (current, 1–30, 31–60, 61–90, over 90), with totals per bucket and per customer.
Graders are probed before they ship. On every seed, the reference solution must pass. Doing nothing, acting at random, stopping one step early, or finishing and then making extra unrequested changes must all fail. Anything a correct solution never changes counts as collateral damage.
| Task | Grade | Reference | Do nothing | Random | Stop early | Extra writes | Footprint |
|---|---|---|---|---|---|---|---|
| ll-01 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[+], nextInvoiceNumber |
| ll-02 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | payments[+], seq |
| ll-03 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | customers[+], invoices[+], nextInvoiceNumber |
| ll-04 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | bankTransactions[*].match, bankTransactions[*].memo, bankTransactions[*].reconciledAt, bankTransactions[*].status, invoices[*].status, payments[+], seq |
| ll-05 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[*].status, invoices[*].voidReason, invoices[*].voidedAt |
| ll-06 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | creditNotes[+], nextCreditNoteNumber |
| ll-07 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | bankTransactions[*].match, bankTransactions[*].memo, bankTransactions[*].reconciledAt, bankTransactions[*].status, expenses[+], seq |
| ll-08 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[*].reminders[+] |
| ll-09 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[*].lines[*].taxRateId, invoices[*].sentAt, invoices[*].sentTo, invoices[*].status |
| ll-10 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | bankTransactions[*].match, bankTransactions[*].memo, bankTransactions[*].reconciledAt, bankTransactions[*].status, invoices[*].status, payments[+], seq |
| ll-11 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[*].lateFees[+], seq |
| ll-12 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | creditNotes[+], nextCreditNoteNumber |
| ll-13 | A | 5/5 pass | fails ✓ | 0/12 | n/a | 1/1 caught | no writes allowed |
| ll-14 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[+], nextInvoiceNumber |
| ll-15 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | bankTransactions[*].match, bankTransactions[*].memo, bankTransactions[*].reconciledAt, bankTransactions[*].status, invoices[*].status, payments[*].bankTxnId, payments[+], seq |
| ll-16 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | bankTransactions[*].match, bankTransactions[*].memo, bankTransactions[*].reconciledAt, bankTransactions[*].status, invoices[*].status, payments[+], seq |
| ll-17 | A | 5/5 pass | fails ✓ | 0/12 | 5/5 fail | 1/1 caught | invoices[+], nextInvoiceNumber |
Fetch the tool definitions in the format your stack expects, start an episode, and let your agent loop. The verifier returns per-check results you can use as a reward signal.
curl -s https://sandworld.dev/api/v1/environments/ledgerline | jq '.formats.anthropic_tools[0]'