Repository navigation
Conversation
Open a details panel from "View details" in an agent card's menu. The panel
shows the agent's configuration, skills, capabilities, input/output modes and
authentication type, and the plugins bound to it. Follows the Figma design and
the existing details panels.
- Read the agent (GET /v1/a2a/{id}) and its card (GET /v1/a2a/{id}/card) on
open; the card supplies skills and modes, and the panel still renders if it
fails. Show only the authentication type, never a credential value.
- List the plugin bindings for the agent's team that name this agent or are
team-wide, and remove one with DELETE /v1/a2a-agents/plugin-bindings/{id}.
- Add tags inline with the shared InlineTagAdd (PUT /v1/a2a/{id} with tags).
- Gate actions on permissions: a2a.update (enable/disable, add tag), a2a.delete,
tools.read (show plugins), tools.manage_plugins (remove a binding).
- Take enabled state and tags from the list entry so the panel follows a toggle
or tag add straight away.
- Remove the description from the list card; clicking a card does nothing.
- Show the stored agent type ("generic" by default) until the gateway stores
the protocol binding. TODO(IBM/mcp-context-forge#7383).
- Add en-US, es-ES and pt-BR strings, unit tests and Playwright tests.
Signed-off-by: Marek Dano <mk.dano@gmail.com>
Open a details panel from "View details" in an agent card's menu. The panel
shows the agent's configuration, skills, capabilities, input/output modes and
authentication type, and the plugins bound to it. Follows the Figma design and
the existing details panels.
- Read the agent (GET /v1/a2a/{id}) and its card (GET /v1/a2a/{id}/card) on
open; the card supplies skills and modes, and the panel still renders if it
fails. Show only the authentication type, never a credential value.
- List the plugin bindings for the agent's team that name this agent or are
team-wide, and remove one with DELETE /v1/a2a-agents/plugin-bindings/{id}.
- Add tags inline with the shared InlineTagAdd (PUT /v1/a2a/{id} with tags).
- Gate actions on permissions: a2a.update (enable/disable, add tag), a2a.delete,
tools.read (show plugins), tools.manage_plugins (remove a binding).
- Take enabled state and tags from the list entry so the panel follows a toggle
or tag add straight away. Ignore fetched data when no agent is selected.
- Remove the description from the list card; clicking a card does nothing.
- Show the stored agent type ("generic" by default) until the gateway stores
the protocol binding. TODO(IBM/mcp-context-forge#7383).
- Add en-US, es-ES and pt-BR strings, unit tests and Playwright tests.
Signed-off-by: Marek Dano <mk.dano@gmail.com>
gcgoncalves
left a comment
There was a problem hiding this comment.
Solid PR, found nits only.
| "agents.connect.manual.description.label": "Description", | ||
| "agents.connect.manual.description.placeholder": "Add an optional description..." | ||
| "agents.connect.manual.description.placeholder": "Add an optional description...", | ||
| "agents.details.region": "Details of {name}", |
There was a problem hiding this comment.
Translation added, but not used.
| const current: AgentDetailsFields | null = | ||
| agent && fetched | ||
| ? { | ||
| ...fetched, | ||
| enabled: agent?.enabled ?? fetched.enabled, | ||
| tags: agent?.tags ?? fetched.tags, | ||
| } | ||
| : agent; |
There was a problem hiding this comment.
useQuery keeps data when its path changes (it only sets isLoading/error; it never clears data). <AgentDetailsPanel> is mounted once in Agents.tsx and re-used for every agent, and the path goes A → null (closed) → B. So after opening agent A and then agent B:
const current = agent && fetched
? { ...fetched, enabled: agent?.enabled ?? fetched.enabled, tags: agent?.tags ?? fetched.tags }
: agent; // ❌ `fetched` is still agent A's until B's request returns- Until B's response arrives, the panel renders A's name, description, endpoint, ID, team, owner, protocol and dates, with B's enabled/tags.
- If B's
GET /v1/a2a/{id}fails, A's data stays on screen alongside the "Couldn't load the agent details." message; the testreports a failed read but keeps showing the list entryonly passes because it renders a single agent. card(skills, modes, capabilities) andbindingListare stale in the same way;bindingsare then filtered by B's name, and the team-wide*bindings of A's team would be shown for B if teams differ.removeBindingcould then delete a binding id belonging to the other team's list.
Recommendation: guard on identity and clear on switch. Smallest fix:
const fetchedForThisAgent = fetched?.id === agentId ? fetched : undefined;
const cardForThisAgent = ... // include id in RegisteredAgentCard or key by agentIdor, simpler and more robust, remount the content per agent:
<AgentDetailsPanel key={detailsId ?? "none"} ... /> // in Agents.tsx| // Only what the panel renders. `Agent` also carries credential fields | ||
| // (authToken, authPassword, ...) that must never reach the UI, so the panel | ||
| // accepts this narrower `Pick`: a stray `{agent.authToken}` is a type error. | ||
| // `authType` is the kind of credential, never its value. | ||
| export type AgentDetailsFields = Pick< | ||
| Agent, | ||
| | "id" | ||
| | "name" | ||
| | "description" | ||
| | "endpointUrl" | ||
| | "agentType" | ||
| | "protocolVersion" | ||
| | "capabilities" | ||
| | "enabled" | ||
| | "reachable" | ||
| | "tags" | ||
| | "authType" | ||
| | "visibility" | ||
| | "team" | ||
| | "teamId" | ||
| | "ownerEmail" | ||
| | "createdAt" | ||
| | "updatedAt" | ||
| | "lastInteraction" | ||
| >; |
There was a problem hiding this comment.
Will this list get replaced by Orval generated types after the backend for A2A is complete? If not, the section below tells the user the agent is unauthenticated when it is not.:
const authType: AuthType | "none" = AUTH_TYPES.includes(current?.authType as AuthType)
? (current?.authType as AuthType)
: "none";It'd be better to fall back to showing something like "Not available" for unknown auth types.
There was a problem hiding this comment.
Good point! Fixed!
- Remount the panel per agent so the previous agent's details, card and
plugin bindings never show while the next one loads or fails to load
- Report an unrecognised authentication type as unknown instead of
presenting it as "No authentication"
- Remove the unused agents.details.region translation
Signed-off-by: Marek Dano <mk.dano@gmail.com>
Summary
Adds the agent details panel from the Figma design. It opens from View details in an agent card's
⋮menu and follows the existing details panels (ResourceDetailsPanel,ToolDetailsPanel).Closes IBM/mcp-context-forge#7518. Part of IBM/mcp-context-forge#7023.
What it shows
Behaviour
GET /v1/a2a/{id}andGET /v1/a2a/{id}/cardon open. The card supplies skills and modes; if it fails, the rest still renders.GET /v1/a2a-agents/plugin-bindings/{team_id}, filtered to this agent and team-wide (*) bindings. Removal usesDELETE .../plugin-bindings/{id}.InlineTagAdd, saved withPUT /v1/a2a/{id}and{ tags }, as on the other pages.a2a.update(enable/disable, add tag),a2a.delete(delete),tools.read(show plugins),tools.manage_plugins(remove a binding).Notes
TODO(IBM/mcp-context-forge#7383).Testing
AgentDetailsPanel.test.tsx,Agents.test.tsx,agents.test.ts(panel content, no credential shown, card failure, plugin list/remove/permissions, tag add, enabled state following the list, menu behaviour). The translation parity test passes.e2e/agents.spec.ts. The agents spec passes (41 tests).Screenshot