AgentCardService¶
Target
This page describes intended behaviour or structure. No implementation is claimed unless a section is explicitly marked Current implementation or Evidence.
| Bounded context | BC-04 Asset Publication |
| Platform / plane | Control Plane / Control |
| Deployment granularity | module of host · host ControlPlaneApi |
| Status | target · ConnectSoft.Factory.Publication.AgentCards |
| Built from | connectsoft-microservice · libraries: connectsoft-extensions-saas-abstractions, connectsoft-extensions-saas-asp-net-core, connectsoft-extensions-messaging-model, connectsoft-extensions-persistence-model-nhibernate |
| Decisions | ADR-0023, ADR-0015 |
| Traceability | FR-02 FR-03 FUX-02 NFR-01 NFR-13 XL-02 |
Purpose and responsibilities¶
ADR-0023 makes the Agent-to-Agent protocol the interop surface between Factory agents and agents outside the Factory (a customer's own agents, a partner's agents, a generated product's embedded agents). AgentCardService is the Control plane half of that decision: it projects each Published agent release into an A2A agent card (skills, input and output descriptors, authentication schemes, task endpoint, release hash), serves discovery with visibility rules, and accepts inbound tasks, which it turns into run submissions in Run Control. Task state is projected back from the run.
The service never executes an agent and never bypasses Run Control: an inbound task is a run like any other, with the caller's workload identity (ADR-0101, SPIFFE-style id) and a delegated scope that cannot exceed what the caller's tenant membership allows.
Context and boundaries¶
flowchart LR
S["AgentCardService"]
ext_generated_products["ext-generated-products"] -->|sync-http| S
S -->|grpc| RunControlService["RunControlService"]
S -->|grpc| IntegrationService["IntegrationService"]
S -. "AgentCardPublished" .-> E_AgentCardPublished(("event"))
S -. "AgentCardWithdrawn" .-> E_AgentCardWithdrawn(("event"))
Visibility: Tenant cards are discoverable by the owning tenant; Partner cards by federated partner identities configured in Integration (BC-16); Public cards by any authenticated caller of GW-01. A card is withdrawn the moment its release is deprecated or revoked, so a partner never discovers an asset that Run Control would refuse to pin.
Domain model¶
AgentCard — Discovery document of one Published agent release: skills, descriptors, authentication, task endpoint and release hash. (catalog entry)
| Field | Type | Required | Description |
|---|---|---|---|
cardId |
guid |
yes | |
tenantId |
string |
yes | |
agentId |
string |
yes | |
releaseId |
string |
yes | |
visibility |
enum:CardVisibility |
yes | |
skills |
list:string |
yes | Skill ids exposed as A2A skills. |
inputDescriptors |
list:string |
yes | |
outputDescriptors |
list:string |
yes | |
authenticationSchemes |
list:string |
yes | oauth2 (Authorization Server), partner-federation |
taskEndpoint |
uri |
yes | Behind GW-01; tasks become runs. |
releaseHash |
hash |
yes | |
publishedAt |
datetime |
yes |
Invariants:
- A card exists only for a Published release and is withdrawn when the release is deprecated or revoked.
- A card never exposes Draft or InReview assets, tool descriptors or policies.
Events: AgentCardPublished, AgentCardWithdrawn · Tables: AgentCards · Repository: AgentCardRepository
erDiagram
AgentCard {
guid cardId PK
string tenantId
string agentId
string releaseId
enum_CardVisibility visibility
list_string skills
list_string inputDescriptors
list_string outputDescriptors
list_string authenticationSchemes
uri taskEndpoint
hash releaseHash
datetime publishedAt
}
A2A task states map onto run states as follows.
| A2A task state | Run state (ADR-0014) |
|---|---|
| submitted | Accepted |
| working | Running |
| input-required | WaitingForApproval, or a step waiting on caller input |
| completed | Completed |
| failed | Failed |
| canceled | Cancelled |
Entities and value objects¶
None modelled
No entities or value objects are modelled for this item yet.
Data model and storage¶
| Store | Role | Engine / profile | Tables |
|---|---|---|---|
| Control plane relational store | primary | azure-sql / nhibernate-sqlserver | AgentCards |
| Table | Owner | Columns | Indexes |
|---|---|---|---|
dbo.AgentCards |
AgentCard | 9 | 1 |
Full DDL: appendix.
APIs¶
| Method | Path | Operation | Scope | Side effects | Idempotency | Gateway | Summary |
|---|---|---|---|---|---|---|---|
GET |
/factory/agent-cards |
ListAgentCards | factory.agents.discover |
read | natural | GW-01 | Discover cards visible to the caller (tenant, partner or public). |
GET |
/factory/agent-cards/{agentId} |
GetAgentCard | factory.agents.discover |
read | natural | GW-01 | The A2A agent card of an agent's current Published release. |
POST |
/factory/agent-cards/{agentId}/tasks |
SubmitA2ATask | factory.agents.invoke |
shared-write | key-header | GW-01 | Inbound A2A task; mapped onto a run submission with the caller's workload identity and delegated scope. |
GET |
/factory/agent-cards/{agentId}/tasks/{taskId} |
GetA2ATask | factory.agents.invoke |
read | natural | GW-01 | Task state projected from the run (submitted, working, input-required, completed, failed, cancelled). |
None modelled
No gRPC methods are modelled for this item yet.
Example card (abridged):
{
"name": "repository-assessor",
"description": "Assesses a repository against ConnectSoft conventions and proposes a change set.",
"url": "https://api.<region>.connectsoft.ai/factory/agent-cards/repository-assessor/tasks",
"version": "1.4.0+9f3c2a1b",
"authentication": { "schemes": ["oauth2"] },
"skills": [ { "id": "repo-scan", "inputModes": ["application/json"], "outputModes": ["application/json"] } ]
}
Messages¶
| Event | Topic | Scope / v | Aggregate | Consumers | Summary |
|---|---|---|---|---|---|
| AgentCardPublished | asset-publication.agent-cards.v1.agent-card-published |
integration / 1 | AgentCard | StudioBff, MarketplaceCatalogService | A card is discoverable. |
| AgentCardWithdrawn | asset-publication.agent-cards.v1.agent-card-withdrawn |
integration / 1 | AgentCard | StudioBff, MarketplaceCatalogService | A card was withdrawn because its release was deprecated or revoked. |
AgentCardPublished payload:
| Field | Type | Required | Description |
|---|---|---|---|
cardId |
guid |
yes | |
tenantId |
string |
yes | |
agentId |
string |
yes | |
releaseId |
string |
yes | |
visibility |
enum:CardVisibility |
yes |
AgentCardWithdrawn payload:
| Field | Type | Required | Description |
|---|---|---|---|
cardId |
guid |
yes | |
tenantId |
string |
yes | |
agentId |
string |
yes | |
reason |
string |
yes |
None modelled
No commands are modelled for this item yet.
| Event | Producer | Handler | Purpose |
|---|---|---|---|
| AssetReleasePublished | AgentRegistryService | PublishCard |
Create or replace the card of an agent release. |
| AssetReleaseDeprecated | AgentRegistryService | WithdrawCard |
Withdraw the card. |
| AssetReleaseRevoked | AgentRegistryService | WithdrawCard |
Withdraw the card. |
Workers and jobs¶
None modelled
No workers are modelled for this item yet.
Actors and grains¶
None modelled
No grains are modelled for this item yet.
Sagas and long-running flows¶
None modelled
No sagas are modelled for this item yet.
Options and configuration¶
| Section | Key | Type | Default | Reloadable | Secret | Summary |
|---|---|---|---|---|---|---|
AgentCards |
DefaultVisibility |
enum | Tenant |
yes | no | Visibility of new cards unless the release declares otherwise. |
Metrics and observability¶
| Metric | Instrument | Unit | Dimensions | Summary |
|---|---|---|---|---|
connectsoft.factory.a2a.tasks_received |
counter | {task} | tenant, agent, callerKind | Inbound A2A tasks. |
Security¶
| Authentication | oauth2-jwt |
| Scopes | factory.agents.discover (Read agent cards.); factory.agents.invoke (Submit and read A2A tasks.) |
| Roles | Requester, PlatformAdmin, Observer |
| Tenant isolation | row-filter |
| Data classification | internal |
| Max side-effect class | shared-write |
| Secrets | — |
Inbound tasks are rate-limited per caller identity at GW-01 and budget-reserved like any run; a partner caller's spend is attributed to the partner agreement's project in the owning tenant.
Dependencies¶
Outbound
| Target | Kind | Purpose | Failure mode | Required |
|---|---|---|---|---|
| RunControlService | grpc | Submit runs for inbound tasks; read run state for task projections. | fail-fast | yes |
| IntegrationService | grpc | Partner credential federation for external callers (BC-16). | fail-fast | no |
Inbound
| Target | Kind | Purpose | Failure mode | Required |
|---|---|---|---|---|
| ext-generated-products | sync-http | Partner and customer agents discover and call Factory agents. | — | yes |
Failure and recovery¶
| Scenario | Detection | Recovery | Data impact | RTO (min) |
|---|---|---|---|---|
| Run Control unavailable for an inbound task | submission fails | A2A task rejected with a retryable error; no task is recorded | none | 15 |
NFR targets¶
| Target | Class value (pilot-interactive) | Override |
|---|---|---|
| latency_p95_ms | 2000 | — |
| availability_pct | 99.5 | — |
| throughput_rps | 50 | — |
| rpo_minutes | 15 | — |
| rto_minutes | 240 | — |
| cost_class | low | — |
Deployment¶
| Granularity | module of host · host ControlPlaneApi |
| Topologies | saas-default, hybrid, on-prem |
| Runtime | —; replicas —–— |
| Ports | — |
Current implementation¶
Nothing exists; no ConnectSoft component speaks A2A today (technology radar: trial, horizon next).
Later capabilities¶
Outbound A2A client for Factory agents calling partner agents (Tools & MCP platform, through a tool of class external); push notifications for task updates; card signing; marketplace listing of public cards (PF-07).
Decisions and traceability¶
| Family | Ids |
|---|---|
| FR | FR-02, FR-03 |
| FUX | FUX-02 |
| NFR | NFR-01, NFR-13 |
| XL | XL-02 |