Skip to content

cc-explorer: agents repeatedly mis-guess tool params (singular-vs-list, session/session_id/src_id, query/max_results bleed) — surface-wide naming/UX friction #36

Description

@coryking

What

Field-testing the cc-explorer tools (observed across several live agent runs) shows a recurring, self-correcting failure at the entry to almost every tool: agents call with the wrong parameter name/shape, eat a pydantic validation error, and retry 1–3 times before the call sticks. Nothing breaks — the verbose errors do teach the right key — but every interrogation/search/forensics call tends to start with one or more wasted round-trips (tokens, latency, and context burned on guess-and-retry).

The guesses are not random. They cluster into a few systemic mismatches between the model's prior and our actual signatures, and several are made worse by the tool surface using different names for the same concept across tools.

Observed failure families (synthetic repros)

  1. Singular string where the signature wants a list. Most frequent.

    • search_projects({patterns: "rsync delta"})-style call written as grep_session({pattern: "a|b|c"}) — singular pattern, plus pipe-OR that the description explicitly discourages.
    • get_agent_detail({agent_id: "aXXXX"}) instead of agent_ids: ["aXXXX"].
      The model's prior is "search takes a string." Descriptions already say "use a list" and the guess still happens — signal that the type, not more prose, is the lever.
  2. No canonical id-param name across the surface. The same concept is spelled three ways:

    • grep_session/browse_sessionsession
    • list_session_agents → also session, but agents repeatedly guess session_id
    • convert_sessionsrc_id
      The on-disk JSONL field is sessionId, so session_id is the model's natural guess — and it is rejected everywhere. Observed: list_session_agents({session_id: ...}) and convert_session({session_id: ...}) / convert_session({session: ..., project: ...}).
  3. Vocabulary bleed from ToolSearch. Agents who just called ToolSearch({query, max_results}) carry that exact vocabulary into search_projects:

    • search_projects({query: "..."}) → should be patterns
    • search_projects({patterns: [...], max_results: 8})max_results is not a param here (the cap lives on grep_session.limit, not on search_projects).
  4. Affordance gaps surfaced by introspection guesses.

    • convert_session({src_id: ..., direction: "help"}) — an agent literally passed "help" to probe the enum; the two valid values and "which direction do I want" aren't legible at call time. (Worth noting: in observed usage session_to_subagent is effectively the only direction used at the entry point.)
    • get_activity_timeline({window: "48h"}) / ({hours: "48"}) — there is no relative-time param, but "last 48h" is the natural ask; took several guesses before falling back to absolute after/before.

Why this is one issue, not six

These are facets of one product-UX problem: parameter naming/typing across the cc-explorer tool surface isn't consistent with each other or with the model's strong priors (and with the adjacent ToolSearch surface). Worth treating as a single surface-wide consistency pass rather than patching each call site.

Breadcrumbs

Not prescribing the API here — capturing the problem + repros so the fix can be designed against the full set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    cc-explorerMCP server and typed JSONL toolkittech-debtCode quality, architecture smells, internal cleanup

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions