feat(agent-card): add metadata field and expose list filter - #502
feat(agent-card): add metadata field and expose list filter#502declan-scale wants to merge 1 commit into
Conversation
Adds an optional `metadata: dict[str, Any]` field to the SDK's `AgentCard` model (defaulting to an empty dict) and threads the value through `AgentCard.from_states` / `AgentCard.from_state_machine` so callers can attach opt-in capability flags without subclassing. Also plumbs the paired platform `agent_card_metadata` list filter through the Stainless-generated `agents.list` surface so consumers can enumerate agents whose card metadata contains a given JSON object with exact key/value semantics. The card continues to serialize through the existing `registration_metadata.agent_card` path — no wire-shape or database migration is required.
basselatscale
left a comment
There was a problem hiding this comment.
The AgentCard.metadata addition and registration propagation look good and provide the missing agent-authored descriptor path.
The list-filter SDK surface needs one change for the intended consumer contract. It is currently typed as Optional[str], which requires callers to know the wire encoding and manually json.dumps the metadata.
Please expose a mapping/JSON-object input and serialize it internally, so both sync and async clients support:
client.agents.list(
agent_card_metadata={"permits_capable": True},
)
Please also add an exercised request-level test for both clients that asserts the mapping becomes a JSON-encoded query parameter. The current generated resource tests pass a sentinel string and are skip-guarded, so they do not prove this behavior.
There is also a currently failing Ruff import-order check in agent_card.py that needs to be fixed.
With that SDK change, these paired PRs provide enough plumbing for the permits harness to discover registered descriptors and remove input-contracts.generated.yaml.
🏆 Brought to you by the Golden Agent (Try it out)
Problem
The SDK's
AgentCardhas no free-form metadata field, so agents that want to advertise opt-in protocol capabilities (e.g. Permits' workflow submission protocol) have no place to attach that self-description data. The generatedagents.listclient also lacks the paired containment filter so consumers can't enumerate agents that opted in.Linear: AGX1-1048
Change
metadata: dict[str, Any] = Field(default_factory=dict)toAgentCardinsrc/agentex/lib/types/agent_card.py. Default factory keeps each instance's dict independent (no shared mutable default).metadata=kwarg throughAgentCard.from_statesandAgentCard.from_state_machineso callers building a card from a state machine can attach metadata inline.registration_metadata.agent_cardpath (agentex.lib.utils.registration.register_agent) — no wire-shape change required.agent_card_metadata: Optional[str]param on both sync and asyncagents.list(a JSON-encoded object matched with exact key/value containment on the server) and adds it toAgentListParams. The platform PR wires the server-side JSONB@>filter.Test coverage added
tests/lib/test_agent_card.pymetadatais an empty dict and instances don't share the default.metadataaccepts arbitrary nested JSON and round-trips throughmodel_dump/model_validate.from_statesandfrom_state_machineforward the value.register_agentpropagatesmetadatainsideregistration_metadata.agent_card.metadataon the outgoing HTTP request.tests/api_resources/test_agents.py: extended the `with_all_params` list tests (sync + async) to pass `agent_card_metadata`. (Still `@pytest.mark.skip`-guarded like the rest of the mock-server tests.)Test plan (for reviewer)
Notes
Fieldis imported from the pydantic already vendored by the SDK.Greptile Summary
The PR adds free-form metadata to
AgentCard, forwards it through state-machine constructors and registration, and exposes a matching sync/asyncagents.listfilter.AgentCardmetadata with serialization and forwarding tests.agent_card_metadatato generated list resource methods and request parameters.Confidence Score: 4/5
The PR appears safe to merge at runtime, but the generated list-filter changes should be made reproducible from the upstream schema before relying on them.
The metadata model and sync/async request paths are internally aligned; the remaining non-blocking concern is that regeneration can discard the manually edited generated client surface.
Files Needing Attention: src/agentex/resources/agents/agents.py, src/agentex/types/agent_list_params.py
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR Builder[AgentCard constructors] --> Card[AgentCard metadata] Card --> Registration[registration_metadata.agent_card.metadata] Registration --> API[AgentEx API] Filter[agents.list agent_card_metadata] --> API API --> Matches[Agents whose card metadata contains filter]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(agent-card): add metadata field and..." | Re-trigger Greptile
Context used (4)