Skip to content

fix(mcp): include SandboxAgents in list_agents and invoke_agent#2249

Open
anxkhn wants to merge 1 commit into
kagent-dev:mainfrom
anxkhn:patch-4
Open

fix(mcp): include SandboxAgents in list_agents and invoke_agent#2249
anxkhn wants to merge 1 commit into
kagent-dev:mainfrom
anxkhn:patch-4

Conversation

@anxkhn

@anxkhn anxkhn commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What

list_agents, the kagent://agents MCP resource, and invoke_agent now return
SandboxAgents (substrate-backed agents) in addition to declarative Agents. A
fully ready SandboxAgent was previously invisible to all three, even though it
shows up in the REST /agents API and the UI.

Why

MCPHandler.listReadyAgents (go/core/internal/mcp/mcp_handler.go) had two
compounding faults:

  1. It listed only v1alpha2.AgentList, so SandboxAgent CRs were never
    enumerated at all.
  2. It gated readiness on the string literal condition.Reason == "DeploymentReady".

A SandboxAgent reports its Ready condition with reason WorkloadReady, while
a declarative Agent uses DeploymentReady:

  • reconcileSandboxAgentStatus sets Reason = AgentReadyReasonWorkloadReady
    when the workload is ready (reconciler.go).
  • reconcileAgentStatus sets Reason = AgentReadyReasonDeploymentReady
    (reconciler.go).

So a SandboxAgent with Accepted=True and Ready=True (reason WorkloadReady)
was dropped by both faults. listReadyAgents feeds handleListAgents (the
list_agents tool) and readAgentsResource (the kagent://agents resource), and
invoke_agent relies on the same readiness notion, so such an agent was reported
as "not found or not ready" over MCP while being fully usable via the REST API.

The correct, two-reason, interface-based readiness check already exists elsewhere
in the codebase and is what this change reuses:

  • isAgentReady in the A2A registrar (a2a/a2a_registrar.go) accepts both
    AgentReadyReasonDeploymentReady and AgentReadyReasonWorkloadReady over the
    AgentObject interface.
  • The REST agents handler (httpserver/handlers/agents.go) does the same.

Fix

  • List both v1alpha2.AgentList and v1alpha2.SandboxAgentList, and evaluate
    readiness through a small readyAgentSummary(v1alpha2.AgentObject) helper that
    operates on the shared AgentObject interface.
  • The helper accepts both reconciler.AgentReadyReasonDeploymentReady and
    reconciler.AgentReadyReasonWorkloadReady, and uses the typed condition-type
    constants (v1alpha2.AgentConditionTypeReady / ...Accepted) with
    metav1.ConditionTrue, matching the A2A registrar and the REST handler instead
    of re-implementing the check with hardcoded strings.
  • Updated the list_agents tool and kagent://agents resource descriptions from
    "accepted + deploymentReady" to "accepted + ready" now that both workload types
    are covered.

No CRD/API types change, so no code generation is required.

Tests

Added TestListReadyAgents_IncludesSandboxAgents in
go/core/internal/mcp/mcp_handler_test.go (table of fake objects via the
controller-runtime fake client already used in this file). It asserts that:

  • a ready declarative Agent (DeploymentReady) is listed,
  • a ready SandboxAgent (WorkloadReady) is listed,
  • a not-ready SandboxAgent is excluded, and
  • the SandboxAgent's description is surfaced.

The test fails against the current code (the SandboxAgent is absent and its
description is empty) and passes with the fix. Revert the mcp_handler.go hunks
to reproduce.

How to verify

cd go
go build ./core/...
go test -race ./core/internal/mcp/...   # incl. TestListReadyAgents_IncludesSandboxAgents
make -C go lint                         # from repo root; 0 issues

Scope

Limited to the MCP agent-listing path. It reuses the existing readiness semantics
(the same two Ready reasons the REST API and A2A registrar already honor) rather
than introducing new behavior, so declarative Agent results are unchanged and
only genuinely ready SandboxAgents are added.

Checklist

  • Commit is DCO signed-off (git commit -s).
  • go build ./core/..., go test -race ./core/internal/mcp/..., and
    make -C go lint all pass.
  • Unit test added; fails without the fix, passes with it.
  • Diff limited to go/core/internal/mcp/mcp_handler.go and its test.

listReadyAgents only enumerated v1alpha2.Agent and gated readiness on the
literal reason "DeploymentReady", so ready SandboxAgents were never listed.
A SandboxAgent reports its Ready condition with reason "WorkloadReady"
(reconciler.reconcileSandboxAgentStatus), while a declarative Agent uses
"DeploymentReady", so a fully ready SandboxAgent (Accepted=True, Ready=True)
was invisible to the list_agents tool and the kagent://agents resource, and
invoke_agent reported it as "not found or not ready" even though it appears
in the REST /agents API and the UI.

List both Agent and SandboxAgent and evaluate readiness over the shared
AgentObject interface, accepting both AgentReadyReasonDeploymentReady and
AgentReadyReasonWorkloadReady, matching the A2A registrar (isAgentReady) and
the REST agents handler. Update the tool and resource descriptions to say
"accepted + ready" now that both workload types are covered.

Closes: kagent-dev#2123
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 15, 2026 00:40
@anxkhn anxkhn requested a review from a team as a code owner July 15, 2026 00:40
@github-actions github-actions Bot added the bug Something isn't working label Jul 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the MCP agent-discovery path so that list_agents, the kagent://agents resource, and the readiness filtering they rely on include both declarative Agent CRs and substrate-backed SandboxAgent CRs, using the shared v1alpha2.AgentObject interface and the same “Accepted + Ready” semantics already used by the REST /agents endpoint and the A2A registrar.

Changes:

  • Expand MCPHandler.listReadyAgents to list both AgentList and SandboxAgentList.
  • Replace hard-coded condition-string readiness checks with a shared readyAgentSummary(v1alpha2.AgentObject) helper that recognizes both DeploymentReady and WorkloadReady ready reasons.
  • Add a regression unit test ensuring ready SandboxAgents are included and their descriptions are surfaced.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
go/core/internal/mcp/mcp_handler.go Lists both Agent and SandboxAgent CRs and applies interface-based readiness checks for MCP agent discovery.
go/core/internal/mcp/mcp_handler_test.go Adds a regression test covering ready vs. not-ready SandboxAgent inclusion and description propagation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +185 to +187
summary := AgentSummary{
Ref: agent.GetNamespace() + "/" + agent.GetName(),
}
Comment on lines +90 to +95
func readyConditions(readyReason string) []metav1.Condition {
return []metav1.Condition{
{Type: "Accepted", Status: metav1.ConditionTrue, Reason: "AgentReconciled"},
{Type: "Ready", Status: metav1.ConditionTrue, Reason: readyReason},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants