Skip to content

[bug] #401's github_list_pulls / github_read_pull are unreachable by EVERY agent — no seeded capabilities.tools declares them, so the Pulls panel works and no agent can answer "what PRs are open?" #415

Description

@serge-ivo

#401 shipped the Pulls panel and, with it, two registry tools so an agent could answer the
question directly: github_list_pulls and github_read_pull (6f6e42f). The panel works. The
tools are unreachable — by every agent on the platform, including the legacy coder.

Ask a Repo Coder "what pull requests are open on this repo?" and it has no tool for it. It will
either decline or reach for the terminal, which is the overlapping drive-path the Coder-2 split
exists to remove.

Correction to the report I was handed

The claim was that "the legacy coder slug declares no allowlist and gets them today." It does
declare one — migration 0054_coder_github_tools.sql re-set coder's full capabilities object,
including "tools":["github_create_issue","github_list_issues","github_read_issue"]. So coder is
on the allowlist path too and is equally blocked. Nothing can call these tools.

Measured, in production

GET /v1/instances/{coder-repo instance}/tools:

{
  "name": "github_list_pulls",
  "connector": "github",
  "scope": "read",
  "allowed": false,
  "disabled": false,
  "reason": "not_declared",
  "writeConsent": "n/a"
}

GET /v1/instances/my/instances, resolved capabilities.tools:

agent declared tools
coder-repo repo_tree, repo_read_file, repo_git, repo_remote, github_list_issues, github_read_issue, github_create_issue
coder-lead list_subordinates, subordinate_status, delegate_goal, check_delegation, github_list_issues, github_read_issue
coder github_create_issue, github_list_issues, github_read_issue
repo-chat search_knowledge, list_knowledge, read_knowledge

Not one carries a pulls tool.

Mechanism

workers/api/src/agent-do-tools.ts:187-203 — a declared list is authoritative, not additive to
a default:

if (declared?.length) {
    set = new Set<string>(BASE);
    for (const name of declared) if (CREATOR_SELECTABLE_TOOLS.has(name)) set.add(name);
}

A name absent from capabilities.tools is never handed to the model, and a text-embedded call to it
is refused. The registry half is complete and correct — lib/connectors/github.ts:190-209 declares
both with scope: "read" (no write consent needed) and :229-230 wires the handlers — so this is
purely the declaration side.

Two correct decisions composing: an authoritative allowlist is exactly what makes a third-party
creator's tool scope safe (#58), and shipping a tool into the registry is the normal way to add
one. Nothing connects them, so a registry addition is inert until a migration says otherwise.

Do

  • One migration. The next free number is 0100 — the highest on main is
    0099_tmux_operator_backend_exclusive_tools.sql. (There are 100 migration files because
    0092 is a historical duplicate pair, recorded as an exception in scripts/check-migrations.mjs;
    the count is not the highest number.)
  • Follow 0054's shape: json_set re-setting the full $.capabilities object so the JSON
    stays one source of truth, idempotent, one UPDATE … WHERE slug = '…' per agent. Do not
    edit 0054/0070check-migrations.mjs --require-history fails a migration whose DDL
    changes after the commit that introduced it.
  • coder-repo and coder: add both tools. They already read and write issues; pull
    requests are the same family and the same auth path.
  • coder-lead: recommend adding both. A Lead reads issues to decide what to delegate; one
    that can see PRs can notice "that is already open in [bug] A negatively-jittered cron run computes its next slot from the early fire time — "@daily" reliably fires twice in one night #412" before spending an Engine on it.
    Owner's call — it widens what the Lead reads, and it is the one of the three where the
    benefit is an argument rather than a gap.
  • repo-chat: recommend not adding. Its declared set is deliberately knowledge-only
    (migration 0050, the first agent built "the creator way") and giving it connector tools is a
    product decision, not a fix for this.

No console change and no instance migration needed: capabilitiesForInstance
(lib/agent-capabilities.ts:524-541) JOINs the agents row at read time, so updating the agent
reaches every already-subscribed instance on the next turn. Verified.

Alternatives considered

Acceptance

  • GET /v1/instances/:id/tools for a coder-repo instance reports allowed: true for
    github_list_pulls and github_read_pull.
  • Asking that instance's Assistant "what pull requests are open on owner/repo?" produces a
    tool.call for github_list_pulls in agent_trace — not a decline and not a terminal
    command.
  • A test asserts the declared lists contain both names, in the shape
    workers/api/src/lib/coder2-parity.test.ts already uses for the issue tools.

Regression risk

  • MAX_DECLARED_TOOLS is 40 (lib/agent-capabilities.ts:343); coder-repo goes 7 → 9. No risk,
    but it is the cap that silently truncates so it is worth naming.
  • coder2-parity.test.ts:131-166 parses migration 0070 by regex (declared0070()) to assert
    the Repo Coder kept the Co-pilot's read tools. After 0100, 0070 is no longer the effective
    declaration and that helper reads a superseded list — it will keep passing while describing the
    wrong state. Either point it at the latest migration touching coder-repo, or re-word it to say
    it only guards that 0070 did not lose anything. Do not leave it silently stale; that is the
    same trap as an expired premise.
  • The tools are scope: "read", so no write-consent surface changes and no new grant is requested
    from any owner.

Files: workers/api/src/lib/connectors/github.ts:190-209,229-230,
workers/api/src/agent-do-tools.ts:187-217, workers/api/src/lib/agent-capabilities.ts:343,524-541,
workers/api/migrations/0054_coder_github_tools.sql, workers/api/migrations/0070_coder_repo_one_chat.sql,
workers/api/src/lib/coder2-parity.test.ts:131-166, scripts/check-migrations.mjs.
Related: #401 (which shipped the tools), #58 (why the allowlist is authoritative).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendBackend / Worker / API workbugSomething isn't workingconnectorsConnector + tool framework

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions