Repository navigation
feat(api): publish the AgentToAgentProvider contract and install artifacts #363
Description
Summary
Replace the placeholder AgentToAgentProvider Rust type with the bounded API
contract needed for A2A v1 discovery, routing, authentication, TLS, placement,
and load inputs. Publish the generated CRD and all install/RBAC artifacts so a
subsequent controller can safely watch and update the resource.
This task defines the API only. It does not add a reconciler or route traffic.
Current state
operator/src/crd/agent_to_agent_provider.rs exists, but it is not an
installed Grid API:
operator/src/bin/generate_crds.rsomits it.deploy/crds/andcharts/grid-operator/templates/crds/have no manifest.- operator RBAC omits the resource and its status subresource.
- The documented Agent Card path is the obsolete
/.well-known/agent.jsonrather than
/.well-known/agent-card.json. AgentCardInfocontains onlyskills: Vec<String>and onemodalities
list, which cannot represent A2A v1 skill IDs, input/output modes,
interfaces, protocol binding, version, or streaming capability.- Status has no discovered-card subset or machine-readable reason.
- The spec has auth but no TLS configuration for Agent Card discovery.
The type has no deployed consumers, so v1alpha1 can be corrected before its
first published manifest instead of preserving a misleading schema.
API decisions
Protocol binding
- The first supported data-plane binding is
JSONRPCover HTTP(S). - Replace the current
protocol: Stringfield with an explicitbinding
enum whose only current variant isJSONRPC. TheAgentToolProvider
precedent usesprotocol: Stringwithdefault = "mcp", but a typed
enum is safer because it lets OpenAPI reject unknown bindings at
admission rather than deferring to controller validation. Future variants
(gRPC, HTTP+JSON) are added when Praxis can classify those bindings. - Keep the existing top-level endpoint as operator-configured authority. An
untrusted card must not silently redirect traffic to another authority.
Agent Card discovery
- Default public card path:
/.well-known/agent-card.json. - Permit an explicit card URL or path override only with a documented URL and
redirect policy that the controller can enforce safely. - Do not store the full external card in Kubernetes status. Define a bounded
observed subset containing only routing-relevant fields.
Skill representation
- Skill identity is the Agent Card
AgentSkill.id, not the display name. - The spec may provide an optional allowlist of skill IDs. Empty means accept
all valid discovered skills. - The observed subset contains bounded entries for ID, name, input modes, and
output modes. Descriptions, tags, examples, schemas, signatures, and
arbitrary extension payloads are not routing state. - Define explicit per-field and per-provider caps that later tasks can use for
status, SWIM, and overlay validation.
Shared provider controls
Reuse established Grid types where their semantics match. These are all
defined in operator/src/crd/inference_provider.rs and
operator/src/crd/auth.rs, and already re-exported for AgentToolProvider:
AccessPolicy- site-scoped consumer authorizationAuthConfig- bearer/header auth for controller probes and data planeEndpointTlsConfig- CA trust and optional mTLS client identitySelectorConfig- site placement selectorTrafficPolicy- drain/admission ({ drain: bool })MetricsConfig- optional Prometheus scraping for queue, latency, error,
and health signals (see Task 5 for which sub-fields A2A uses)capacity_weight: Option<u32>(range 1-1000) - explicit positive capacity
for placement policy, same asInferenceProvider.spec.capacity_weight
Document that auth/TLS apply both to safe controller discovery and to the
final private-agent hop, while Secret values never enter status or overlays.
AgentToolProvider does not have MetricsConfig, TrafficPolicy, or
capacity_weight today. A2A needs them from the start because Task 5
(scoring) and Task 4 (overlay) depend on the CRD providing these fields.
Status
Add a status shape sufficient for later consumers:
phasereasonmatchingSitesobservedGeneration- bounded observed agent name and version
- selected protocol binding and streaming capability
- bounded discovered/allowed skills
Document stable reason values that the controller task will implement,
including invalid config, missing network, credential/TLS failures,
unreachable card, invalid card, unsupported binding, and no routable skills.
Implementation
- Update
operator/src/crd/agent_to_agent_provider.rsand unit/schema tests. - Include the CRD in
operator/src/bin/generate_crds.rs. - Generate
deploy/crds/agenttoagentprovider.yaml. - Generate the Helm CRD template under
charts/grid-operator. - Add resource and status verbs to deployment and Helm ClusterRoles.
- Add a minimal current sample under
config/samples/. - Update CRD, architecture, operations, and chart documentation.
- Add chart and CRD-staleness tests matching the other provider CRDs.
Acceptance criteria
- A clean install creates
agenttoagentproviders.grid.praxis.fast. - The operator ServiceAccount can get/list/watch the resource and get/patch
its status, without broader Secret permissions. - The schema represents A2A v1 Agent Card skill IDs, binding, streaming,
input/output modes, auth, TLS, access policy, placement, drain, and optional
load inputs. - The schema rejects blank identifiers, invalid bounds, and impossible
mutually exclusive fields where OpenAPI can express the rule. - Status is bounded and contains no credential values or arbitrary full-card
JSON. - Existing installed CRDs remain byte-for-byte unchanged except for the
generated list gaining the new resource. make generate-crds,make crds-check, focused operator tests, Helm tests,
formatting, and Clippy pass.
Non-goals
- Fetching or validating an Agent Card.
- SWIM/CRDT propagation.
- Routing overlay candidates.
- gRPC or HTTP+JSON request routing.
- Defining the Praxis request extension used to select a skill.
Related to
- Parent: Cross-gateway A2A routing ai#206
- Reference pattern:
AgentToolProvider - Parent epic: Epic: Gateway-to-Gateway Connectivity, Metadata and Routing ai#197
Activity
liavweiss commentedon Oct 12, 2026
/assign