01Safety
0.0 / 30
What changed in the harness
Selection accuracy 98→100, token cost up 9%, unconfirmed writes 0%→0%.
Category breakdown
Earned points across the four signals Gradable measures. Safety and Legibility are scored out of 30; Economics and Discoverability are scored out of 20.
0.0 / 30
18.5 / 30
14.7 / 20
16.1 / 20
Highest-impact fix
Estimated gain +30 pointsExpose machine-readable principal/tenant confirmation and a non-mutating permission check so agents can verify both before destructive actions.
Description evidence
35 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 |
|---|---|---|
lithtrix_memory_set |
no_return_description |
Store or update a JSON value under a memory key (PUT /v1/memory/{key}) and return the stored memory record so you can confirm persistence. Requires LITHTRIX_API_KEY. Optional ttl (seconds), importance, source, and confidence modulate retention and provenance. |
lithtrix_memory_get |
no_return_description |
Retrieve a stored memory by key (GET /v1/memory/{key}) and return its stored value. Requires LITHTRIX_API_KEY. |
lithtrix_memory_context |
no_return_description |
Return the top memories for session start (GET /v1/memory/context), ranked by importance then recency, so you can restore context. Requires LITHTRIX_API_KEY. Optional limit (1-50, default 10) and importance tier filter. |
lithtrix_blob_upload |
no_return_description |
Upload binary bytes as a new blob (PUT /v1/blobs, raw body + Content-Type) and return the blob record including its content-addressed blob_id (b_ + 16 hex) for later download, parse, or deletion. Requires LITHTRIX_API_KEY. Decode base64 from content_base64; prefer direct HTTP multipart/raw PUT for large files. Subject to BLOB_MAX_UPLOAD_BYTES and BLOB_STORAGE_LIMIT. |
lithtrix_blob_list |
no_return_description |
List your stored blob metadata records (GET /v1/blobs) and return them, paginated by the optional page and per_page parameters. Requires LITHTRIX_API_KEY. |
lithtrix_blob_meta |
no_return_description |
Fetch the metadata JSON for one blob by its content-addressed blob_id (GET /v1/blobs/{blob_id}/meta) and return it. Requires LITHTRIX_API_KEY. |
lithtrix_blob_delete |
name_restates_behavior no_return_description |
Delete a blob you no longer need by its content-addressed blob_id (DELETE /v1/blobs/{blob_id}) so it stops being served or listed, and return the deletion confirmation; the delete is a soft-delete, so confirm the API response before assuming permanent removal. Requires LITHTRIX_API_KEY. |
lithtrix_blob_signed_url |
no_return_description |
Mint and return a time-limited HTTPS read URL for a blob (GET /v1/blobs/{blob_id}/signed-url), so you can share read access without exposing your API key. Anyone with the URL can GET bytes until expiry, so share it carefully. Optional expires_in TTL in seconds (min 60; omit for API default). Requires LITHTRIX_API_KEY. |
lithtrix_blob_parse |
no_return_description |
Extract text/tables from a blob (POST /v1/blobs/{blob_id}/parse) and return a parse result with a parse_id for polling; set async=true for QStash processing and optionally provide callback_url for completion. Requires LITHTRIX_API_KEY. |
lithtrix_blob_parse_status |
no_return_description |
Poll a blob parse operation (GET /v1/blobs/{blob_id}/parse/{parse_id}) identified by blob_id and parse_id, and return its current status and the extracted result once complete. Requires LITHTRIX_API_KEY. |
lithtrix_blob_search |
no_return_description |
Semantic search over chunks parsed from your blobs (GET /v1/blobs/search) and return ranked hits with similarity scores; optional limit and minimum threshold (0-1) control results. Shares quota with web search. Requires LITHTRIX_API_KEY. |
lithtrix_feedback_interaction |
no_return_description |
Record and return confirmation of an agent-on-agent reputation signal (positive/negative/neutral) via POST /v1/feedback/interaction, used for reputation routing. Distinct from content-quality lithtrix_feedback. Requires LITHTRIX_API_KEY. |
lithtrix_reputation_dispute |
no_return_description |
Dispute a reputation event where you are the subject (POST /v1/reputation/dispute, max 3 per UTC day) and return the dispute result so you can track review. Provide the reputation event UUID and the reason it should be reviewed. |
lithtrix_commons_read |
no_return_description |
List opt-in shared public memory entries from Lithtrix Commons (GET /v1/commons/entries) and return the entry records, paginated by optional page and per_page. Does not debit credits for commons reads, but per-minute rate limits still apply. Requires LITHTRIX_API_KEY. Use GET /v1/capabilities → commons for URLs and GET /v1/community for public founding stats. |
lithtrix_keys_list |
no_return_description |
List your agent's scoped sub-keys (GET /v1/keys) and return them so you can manage, rotate, or revoke them. Requires the root LITHTRIX_API_KEY. |
lithtrix_keys_rotate |
no_return_description |
Rotate a scoped sub-key (POST /v1/keys/{key_id}/rotate) and return the new key material; the prior key honors grace_hours (default 24) before expiring. key_id is the sub-key UUID from lithtrix_keys_list. Requires root Bearer. |
lithtrix_keys_revoke |
no_return_description |
Immediately revoke a scoped sub-key (DELETE /v1/keys/{key_id}) and return confirmation that the key is no longer valid. key_id is the sub-key UUID from lithtrix_keys_list. Requires root Bearer. |
lithtrix_passport_get |
params_unexplained |
Fetch an agent's passport (GET /v1/agents/{agent_id}/passport), where agent_id is the target agent's UUID, and return its public DID and PEM public key without authentication. When reputation_sub_signal_visibility is decomposed, the response may include reputation_sub_signals (search_quality, memory_reliability, interaction_success_rate; null when sparse). |
lithtrix_passport_revoke |
no_return_description |
Revoke your Ed25519 passport (POST /v1/me/passport/revoke) and return confirmation that it is no longer valid for agent authentication. Requires root ltx_* API key. |
lithtrix_passport_auth_challenge |
params_unexplained no_return_description |
Mint and return a short-lived nonce challenge (POST /v1/auth/passport/challenge, no Bearer) used as input for passport authentication; agent_id is the UUID of the agent requesting the challenge, and the returned nonce is later signed in the verify step. |
lithtrix_passport_auth_verify |
params_unexplained no_return_description |
Verify an Ed25519 passport signature (POST /v1/auth/passport/verify) and return an ltx_session_* token on success. agent_id is the agent UUID, challenge_id is the challenge UUID from the challenge step, and signature is the Ed25519 signature over the challenge (min 8 chars). |
lithtrix_passport_set_capabilities |
params_unexplained no_return_description |
Replace the operator's passport capabilities.self_reported (POST /v1/agents/passport/capabilities) and return the updated capabilities. capabilities is an object with a required self_reported array of capability strings (each 1-96 chars, max 48). Requires root ltx_* or ltx_session_* token. |
lithtrix_passport_set_description |
params_unexplained no_return_description |
Update bio, skills, listed, and/or reputation_sub_signal_visibility on your passport (POST /v1/agents/passport/description) and return the updated passport. bio is a free-text bio (max 500 chars or null); skills is a list of skill strings (1-50 chars, max 20); listed controls directory visibility (defaults false); reputation_sub_signal_visibility is decomposed (per-signal breakdown) or aggregate_only (defaults decomposed). Requires root ltx_* or ltx_session_*. |
lithtrix_passport_derive |
params_unexplained no_return_description |
Derive and return deterministic Ed25519 passport PEMs locally from LITHTRIX_PASSPORT_MASTER_SEED plus the agent UUID (agent_id); the seed is never sent to Lithtrix. agent_id is the UUID the passport is derived for. |
lithtrix_passport_ephemeral |
params_unexplained no_return_description |
Create and return a session-scoped Ed25519 passport plus an ltx_session_* token (POST /v1/auth/passport/ephemeral) for the agent UUID (agent_id), for stateless sandboxes. |
lithtrix_passport_stake |
params_unexplained no_return_description |
Lock platform credits for a passport stake tier (POST /v1/agents/passport/stake) and return the resulting stake status. tier selects the stake level: low, medium, or high. Requires root ltx_* Bearer. |
lithtrix_passport_unstake |
no_return_description |
Begin the unstake cooling period for your passport stake (POST /v1/agents/passport/unstake) and return confirmation so you know when the locked credits become available. Requires root ltx_* Bearer. |
lithtrix_passport_sponsor |
params_unexplained no_return_description |
Vouch for a ward agent (POST /v1/agents/{sponsor_id}/sponsor/{ward_id}) and return the resulting sponsorship record. sponsor_id is your agent UUID (Bearer must match it); ward_id is the agent being sponsored. |
lithtrix_passport_sponsor_revoke |
params_unexplained no_return_description |
Start the sponsor revocation grace period for a ward (POST /v1/agents/{sponsor_id}/sponsor/{ward_id}/revoke) and return confirmation/status. sponsor_id is your agent UUID (Bearer must match it); ward_id is the sponsored agent. |
lithtrix_agent_vouch |
params_unexplained no_return_description |
Vouch for a skill on another agent (POST /v1/agents/{target_agent_id}/vouch) and return the recorded vouch. target_agent_id is the UUID of the agent being vouched for; skill is the skill string (1-50 chars). Bearer is the voucher. |
lithtrix_agent_vouch_revoke |
params_unexplained no_return_description |
Revoke your skill vouch for another agent (POST /v1/agents/{target_agent_id}/vouch/revoke) and return confirmation. target_agent_id is the UUID of the agent; skill identifies the vouched skill (1-50 chars). Only the original voucher (Bearer) may revoke. |
lithtrix_spawn |
no_return_description |
Spawn a scoped swarm child (POST /v1/agents/{parent_agent_id}/spawn) and return the child record including child_agent_id and its scoped sub-key, ready for delegation. Requires root LITHTRIX_API_KEY. Optional agent_name (server generates swarm-{uuid8} if omitted), scope (default memory-only), ttl_seconds key-expiry hint, and issue_ephemeral_passport. |
lithtrix_delegate |
params_unexplained no_return_description |
Issue a signed delegation contract (POST /v1/agents/{parent_agent_id}/delegate) and return the delegation including delegation_id and the locally signed contract. parent_agent_id is the delegating parent UUID (inferred from GET /v1/me when omitted); recipient_agent_id is the recipient UUID (typically child_agent_id from lithtrix_spawn); task_id correlates delegation and trace (auto-generated when omitted); read_set/write_set are declarative scope labels (default memory); assumptions is an arbitrary map stored in the contract (default {}); version_refs are optional version pins (default []); ttl_seconds sets contract TTL (default 3600); verifier_obligations is an optional verifier obligations object (omit or null to skip); conflict_policy must be last_writer_wins_audit. Signs locally with the passport key. |
lithtrix_trace_append |
no_return_description |
Append an audit event to a task trace (POST /v1/tasks/{task_id}/trace/events) and return the recorded event; it records only, with no runtime veto. Provide task_id, proposed_action (e.g. memory.put), and decision (e.g. allowed); optionally delegation_id, scope_json, evidence_json, outcome, and advisory_claims. |
lithtrix_trace_get |
no_return_description |
Read a task's audit trace (GET /v1/tasks/{task_id}/trace) and return the recorded trace events; only task participants may call. task_id is the task UUID from lithtrix_delegate. |
Selection evidence
15 pairs where similar names or overlapping descriptions may send an agent toward the wrong tool.
| Tool A | Tool B | Confidence | Why they collide |
|---|---|---|---|
lithtrix_feedback |
lithtrix_feedback_interaction |
medium | Both tools accept a signal plus optional note; a task like 'send positive feedback' or 'rate this response' is ambiguous when the target (search result vs other agent) is not explicit, even though one is content-quality and the other agent reputation. |
lithtrix_search |
lithtrix_blob_search |
medium | Both are query-based search tools returning ranked results; a bare task like 'search for information about X' without specifying the web vs uploaded/parsed documents could route to either, since both take only q and limits. |
lithtrix_search |
lithtrix_memory_search |
medium | Both are 'search' tools with q, limit, and threshold-shaped inputs; 'find information about X' is ambiguous between live web search and searching stored memories unless the scope is explicitly stated. |
lithtrix_agent_vouch |
lithtrix_agent_vouch_revoke |
medium | Identical schemas (target_agent_id + skill) and both are about skills on an agent; phrases like 'I no longer endorse X for Rust' or 'take back my vouch' could select the wrong one based on surface wording rather than the revoke verb. |
lithtrix_passport_sponsor |
lithtrix_passport_sponsor_revoke |
medium | Identical parameters (sponsor_id, ward_id) and both concern the same sponsorship relationship; tasks like 'remove my sponsorship' or 'stop vouching for this ward' are ambiguous if the agent keys on 'sponsor' rather than the revoke action. |
lithtrix_passport_rotate |
lithtrix_passport_revoke |
medium | Both are no-argument, root-required passport lifecycle actions with overlapping verbs; a task like 'my passport was compromised, reset/replace it' or generally 'deactivate my passport' could pick rotate instead of revoke or vice versa. |
lithtrix_keys_rotate |
lithtrix_keys_revoke |
medium | Same key_id schema and same key-management domain; 'kill this API key' vs 'roll my key' are clear, but a task like 'my key was leaked, rotate it' could be misread as revoke if the agent interprets rotation as an immediate disabling. |
lithtrix_passport_auth_challenge |
lithtrix_passport_auth_verify |
medium | Both are steps of the same passport authentication flow with agent_id inputs; a task like 'authenticate this agent's passport' is ambiguous about whether to mint the nonce (challenge) or complete the exchange (verify), and both sound like 'auth'. |
lithtrix_passport_set_capabilities |
lithtrix_passport_set_description |
medium | Both are passport-update tools sharing agent/passport/set/root/session tokens; a task like 'update my passport' or 'declare what I can do' could route to capabilities when the user meant skills/bio in description, or vice versa. |
lithtrix_memory_get |
lithtrix_memory_search |
medium | Both retrieve memories and accept an identifier-like input; 'get what I know about X' without an exact memory key is ambiguous between fetching by key (get) and semantic lookup (search), since get requires an exact key the user may not have. |
lithtrix_keys_rotate |
lithtrix_passport_rotate |
medium | Both are 'rotate' actions on credentials and both require the root key; a task like 'rotate my credentials/secrets' is ambiguous about whether it targets a scoped API key or the Ed25519 passport, which are different tools. |
lithtrix_passport_derive |
lithtrix_passport_ephemeral |
medium | Both produce Ed25519 passports for an agent_id; a task like 'create/generate a passport for agent X' is ambiguous between the deterministic local derivation and the session-scoped ephemeral issuance, which have different trust implications. |
lithtrix_blob_parse |
lithtrix_blob_parse_status |
low | A task like 'get the parse of blob X' could trigger a fresh parse instead of polling an existing parse job; mostly distinct because status requires a parse_id and 'status' wording disambiguates, but confusion is still possible when the user just wants the parse outcome. |
lithtrix_passport_revoke |
lithtrix_passport_sponsor_revoke |
low | Both embed 'passport' and 'revoke'; however 'revoke my passport' naturally maps to passport_revoke and 'revoke sponsorship' to sponsor_revoke, so confusion only arises with abridged phrasing like just 'revoke this'. Plausible but unlikely. |
lithtrix_memory_get |
lithtrix_memory_context |
low | A task like 'load/show me my memories' could be interpreted as fetching a single key (get) versus reloading the top session memories (context), but context has no key input and get requires one, so genuine confusion is limited. |
Compare the field