Skip to content

Signed AgentCard always has empty skills/capabilities in automated deploy path #292

Description

@pdettori

Summary

The automated deployment path produces a signed AgentCard with empty skills and capabilities. The signing infrastructure works correctly, but the content pipeline into it doesn't carry the agent's real capabilities.

Current Behavior

  1. The backend creates <name>-card-unsigned ConfigMap with a hardcoded skeleton:

    {"name": "<name>", "url": "...", "capabilities": {}, "skills": []}

    (kagenti/backend/app/routers/agents.py_ensure_card_unsigned_configmap)

  2. The sign-agentcard init container signs this skeleton with the pod's SPIRE SVID and writes to /app/.well-known/agent-card.json

  3. The controller fetches the signed-but-empty card from the live endpoint and verifies the signature

Result: The signed card is always empty, and the rich card (from the agent framework) is always unsigned. There is no automated path for a developer to get a signed AgentCard with the agent's true capabilities.

Current Workaround

ensure_configmap is create-if-not-exists, so pre-creating the ConfigMap with real content (as in demos/agentcard-spire-signing/) prevents the backend from overwriting it. Editing the ConfigMap post-deploy and bouncing the pod also works. Both require manual/GitOps intervention.

Proposed Solutions

These are not mutually exclusive:

1. Accept skills/capabilities in the deploy API

Extend CreateAgentRequest so the backend populates the unsigned ConfigMap with real content at creation time. Simplest change; works for agents whose capabilities are known at deploy time.

2. Two-phase sign: fetch-then-sign

After the agent is running, a controller or CronJob fetches /.well-known/agent-card.json from the live agent, patches the unsigned ConfigMap with the real content, and triggers a pod restart to re-sign. Handles agents whose capabilities are discovered at runtime (dynamic skills, plugin-loaded tools, etc.).

3. Agent-side signing

Instead of an init container signing a static ConfigMap, the agent framework itself signs the card using the SPIRE SVID at startup. The SDK calls the Workload API, signs its own dynamically-generated card, and serves the signed version directly. No ConfigMap needed. Most A2A-native approach but requires SDK integration.

References

  • kagenti/backend/app/routers/agents.py:2029-2060_ensure_card_unsigned_configmap
  • kagenti-operator/cmd/agentcard-signer/main.go — signer init container
  • kagenti-operator/internal/controller/agentcard_controller.go:220-232 — controller fetch + verify
  • kagenti-operator/demos/agentcard-spire-signing/ — working demo with manually crafted ConfigMap

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions