0.0 / 30
What changed in the harness
Selection accuracy 100→100, token cost up 13%, unconfirmed writes 0%→0%.
Category breakdown
Where the score comes from.
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
01Safety
02Legibility
18.4 / 30
03Economics
17.5 / 20
04Discoverability
13.0 / 20
Highest-impact fix
Estimated gain +30 pointsAdd explicit identity and permission preflight tools
Expose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
Defects and rewrites.
37 defects found across the exposed tool descriptions. Suggested rewrites make purpose, inputs, boundaries, and returns easier for an agent to understand.
| Tool | Defect types | Suggested rewrite |
|---|---|---|
check_balance |
name_restates_behavior no_return_description |
Retrieve the current Lightning balance in satoshis for the active account. Works with both operator and agent keys. Returns the balance amount in satoshis. |
pay_l402_api |
no_return_description |
Send an HTTP request to a paid API. Supports L402 (Lightning) and X402 (USDC on Base) protocols; if the API responds with HTTP 402, automatically detects the protocol and pays the required amount, preferring L402 when both are available. Set max_payment_sats to cap the auto-payment (default 1000). REQUIRES AGENT KEY. Returns the API response body along with the amount paid in satoshis, if any. |
create_invoice |
no_return_description |
Create a Lightning invoice to receive payment. Returns the BOLT11 invoice and its payment_hash; pass the payment_hash to get_invoice_status to check if it has been paid. |
get_invoice_status |
no_return_description |
Check whether a previously created invoice has been paid. Pass the payment_hash returned by create_invoice. Returns the current payment status of the invoice. |
update_operator |
no_return_description |
Update the operator profile by setting an email address (a verification link is emailed - required for the free-sats promo) and/or a display name. REQUIRES OPERATOR KEY. Returns the updated operator profile. |
claim_promo |
no_return_description |
Claim the free-sats install promo (100 sats, first 100 installs). Requires a verified email (set one with update_operator, then click the emailed link) and an operator account at least 3 hours old. Pass a promo_code to use a different promo if applicable. REQUIRES OPERATOR KEY. Returns the number of sats credited to the operator balance. |
get_deposit_invoice |
no_return_description |
Create a Lightning invoice to fund your operator account; paying it adds sats to your balance. Returns the BOLT11 invoice to pay for the requested amount_sats. |
create_agent |
params_unexplained |
Create a new agent under your operator account and return its API key. name is required; description is an optional human-readable note stored for reference and does not affect agent behavior; budget_limit_sats sets an optional spending cap in sats (0 for unlimited). |
fund_agent |
no_return_description |
Transfer sats from the operator balance to an agent. Returns a confirmation of the transfer, including the updated agent balance. |
list_agents |
name_restates_behavior no_return_description |
List all agents under your operator account. Returns each agent with its ID and name, which you can use with fund_agent, set_budget, and get_budget_status. |
set_operator_key |
no_return_description |
Switch to a different operator API key for subsequent requests. Use after register_operator to start using the new credentials. Returns a confirmation that the new key is now in effect. |
set_agent_credentials |
no_return_description |
Switch to an agent API key for subsequent requests. Use to operate as a specific agent after creating it. Returns a confirmation that the agent key is now in effect. |
register_webhook |
name_restates_behavior no_return_description |
Register a webhook URL to receive payment notifications for the current agent; a maximum of 5 webhooks per agent are allowed. Returns the created webhook with an ID you can use with test_webhook and delete_webhook. REQUIRES AGENT KEY. |
list_webhooks |
no_return_description |
List all registered webhooks for the current agent. Returns each webhook's ID, URL, and subscribed events, which you can use to test or delete webhooks. REQUIRES AGENT KEY. |
delete_webhook |
no_return_description |
Delete a registered webhook for the current agent using its webhook_id. Returns a confirmation that the webhook was removed. REQUIRES AGENT KEY. |
test_webhook |
no_return_description |
Send a test event to a registered webhook to verify it is working. Returns the result of the delivery attempt. REQUIRES AGENT KEY. |
get_budget_status |
name_restates_behavior no_return_description |
Retrieve budget status for an agent, including the configured limit, amount spent, and amount remaining in satoshis. Pass agent_id to query a specific agent (operators only) or omit it to query the current agent. Works with operator or agent keys. |
set_budget |
no_return_description |
Set or update the spending budget for an agent; budget_limit_sats is the new limit in sats, with 0 meaning unlimited. REQUIRES OPERATOR KEY. Returns the agent's updated budget status. |
deactivate_agent |
name_restates_behavior no_return_description |
Deactivate an agent so it cannot make payments until it is reactivated with reactivate_agent. REQUIRES OPERATOR KEY. Returns a confirmation of the deactivation. |
reactivate_agent |
name_restates_behavior no_return_description |
Reactivate a previously deactivated agent so it can make payments again; use deactivate_agent to disable it again. REQUIRES OPERATOR KEY. Returns a confirmation of the reactivation. |
rotate_api_key |
no_return_description |
Generate a new API key, invalidating the old one, and return the new API key. For operators: triggers a 60-minute withdrawal cooldown. For agents: a 30-minute cooldown. Pass agent_id to rotate an agent's key (operators only); omit it to rotate the operator key. |
get_info |
no_return_description |
Get service information and return the service version, status, current limits, and supported features. No API key required - works before registering. |
get_rate_limits |
name_restates_behavior no_return_description |
Check current API rate limit usage to gauge how many requests you can still make before being throttled. Returns the number of requests remaining and the time until the current rate limit window resets. |
withdraw |
name_restates_behavior no_return_description |
Send sats from the operator balance to an external Lightning invoice, for example to move funds out of the service or pay a recipient's invoice. REQUIRES OPERATOR KEY. Subject to a security cooldown that may delay execution. Returns the outbound payment result once the invoice is paid. |
create_withdraw_link |
no_return_description |
Create an LNURL-withdraw link so the operator can pull funds from the service into any Lightning wallet. Opens a QR code in the browser for wallet scanning; omit amount_sats to sweep the full balance. REQUIRES OPERATOR KEY. Returns the generated LNURL-withdraw link for sharing or scanning. |
sweep_agent |
name_restates_behavior no_return_description |
Move sats from an agent's balance back to the operator balance, for example when retiring an agent or consolidating funds. REQUIRES OPERATOR KEY. Pass a large amount_sats to sweep the full agent balance. Returns the transfer details, including the amount moved. |
pay_lightning_address |
name_restates_behavior no_return_description |
Send sats from the agent's balance to a Lightning address (user@domain.com), enabling payments to recipients that don't expose a BOLT11 invoice. REQUIRES AGENT KEY. Returns the payment result once the payment is sent. |
set_nostr_identity |
name_restates_behavior no_return_description |
Set the agent's Nostr identity, required before it can use Nostr features such as zaps. Stores the provided private key and derives the corresponding public key for signing and receiving. REQUIRES AGENT KEY. Returns confirmation with the derived public key. |
get_nostr_identity |
no_return_description |
Get the agent's configured Nostr identity. REQUIRES AGENT KEY. Returns the Nostr public key (hex) and its npub encoding. |
nostr_zap |
no_return_description |
Send a Nostr zap - a NIP-57 Lightning payment with an optional attached Nostr event. If the recipient supports NIP-57, a proper zap receipt is created; otherwise it falls back to a regular Lightning address payment. REQUIRES AGENT KEY with a Nostr identity set. Returns the payment result and zap receipt status. |
transfer_to_agent |
name_restates_behavior no_return_description |
Move sats between agents or from the operator balance to an agent, useful for funding agents or redistributing balances. REQUIRES OPERATOR KEY. Omit from_agent_id to take funds from the operator balance. Returns a transfer confirmation, including the amount moved. |
lnurl_auth |
name_restates_behavior no_return_description |
Log in to a service using the LNURL-auth protocol so the agent can authenticate to Lightning-enabled services without passwords. REQUIRES AGENT KEY. Returns whether authentication succeeded. |
claim_lnurl_withdraw |
name_restates_behavior no_return_description |
Claim available funds from an LNURL-withdraw link into the agent's balance, for example when a service issues a withdraw coupon or faucet payout. REQUIRES AGENT KEY. Returns the claimed amount once funds are received. |
keysend |
no_return_description |
Send sats directly to a Lightning node without requiring an invoice, using keysend/spontaneous payments. Useful for tipping or paying nodes that don't issue invoices. REQUIRES AGENT KEY. Returns the payment result once sent. |
board_post |
no_return_description |
Post a message to the Lightning Faucet agent board to share insights, ask questions, or start discussions with other AI agents. Your first 10 posts are free; afterwards each post costs 1 sat, with a minimum of 20 characters. REQUIRES AGENT KEY. Returns the new post's ID once published. |
board_reply |
no_return_description |
Reply to an existing post on the agent board to continue a discussion with other agents. Costs 1 sat, or is free if you still have free actions remaining. REQUIRES AGENT KEY. Returns the reply's ID once published. |
board_vote |
no_return_description |
Vote up or down on a post to influence its ranking on the agent board. Paid upvotes (1 sat) also reward the author 0.5 sats on average; free votes affect ranking only. REQUIRES AGENT KEY. Returns the updated vote status. |
Selection evidence
Confusable tool pairs.
14 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
fund_agent |
transfer_to_agent |
high | Both move sats into an agent; transfer_to_agent explicitly supports operator-to-agent transfers, so tasks like 'send/transfer sats to an agent' are ambiguous between the two. |
set_operator_key |
set_agent_credentials |
high | Both do the same action—switch the API key for subsequent requests—differing only by key type. A task like 'use this new API key' is ambiguous without specifying operator vs agent. |
create_invoice |
get_deposit_invoice |
medium | Both create a Lightning invoice to receive sats; only the destination (agent vs operator account) differs. 'Create an invoice to receive payment' could select either. |
create_invoice |
create_withdraw_link |
medium | Both create a mechanism to receive sats (BOLT11 invoice vs LNURL-withdraw link); a task like 'set up a way to receive funds' is ambiguous. |
withdraw |
create_withdraw_link |
medium | Both are operator withdrawal routes (payout to an invoice vs generating an LNURL-withdraw link). 'I want to withdraw sats' doesn't clearly pick one. |
create_withdraw_link |
claim_lnurl_withdraw |
medium | LNURL-withdraw appears in both; a task like 'withdraw/claim using a lnurl link' is ambiguous between generating the link and claiming from an existing one. |
claim_promo |
claim_lnurl_withdraw |
medium | Both are 'claim' actions that add sats to a balance; 'claim my sats/funds' could route to either, especially without the promo context. |
pay_invoice |
decode_invoice |
medium | Both accept a bolt11 string and neither requires an operator context; a task like 'process/verify this invoice' (check before paying, or just inspect) is ambiguous. |
set_nostr_identity |
get_nostr_identity |
medium | Set/get pair sharing the same noun; 'I need my Nostr identity' is ambiguous between storing the private key and fetching the public key. |
get_invoice_status |
get_budget_status |
medium | Near-identical 'get X status' naming; a vague task like 'check the status' does not reveal whether the invoice or budget is meant. |
deactivate_agent |
delete_agent |
medium | Both 'remove/disable' an agent; a task like 'take my agent offline' or 'remove this agent' is ambiguous between temporary deactivation and permanent deletion. |
register_operator |
update_operator |
medium | Both can set an email/name; 'register/set my email or account info' could select either since register_operator accepts an email and update_operator is for profile changes. |
fund_agent |
sweep_agent |
medium | Opposite directions of the same operator↔agent balance transfer; a task like 'move sats between my agent and operator' is ambiguous on direction. |
get_budget_status |
get_info |
medium | Both expose 'limits'; a task like 'check my limits/status' is ambiguous between per-agent budget limits and general service limits. |
Compare the field