LabAcacia.A2aIngress
1.0.0-alpha.16
architecture adjustment
dotnet add package LabAcacia.A2aIngress --version 1.0.0-alpha.16
NuGet\Install-Package LabAcacia.A2aIngress -Version 1.0.0-alpha.16
<PackageReference Include="LabAcacia.A2aIngress" Version="1.0.0-alpha.16" />
<PackageVersion Include="LabAcacia.A2aIngress" Version="1.0.0-alpha.16" />
<PackageReference Include="LabAcacia.A2aIngress" />
paket add LabAcacia.A2aIngress --version 1.0.0-alpha.16
#r "nuget: LabAcacia.A2aIngress, 1.0.0-alpha.16"
#:package LabAcacia.A2aIngress@1.0.0-alpha.16
#addin nuget:?package=LabAcacia.A2aIngress&version=1.0.0-alpha.16&prerelease
#tool nuget:?package=LabAcacia.A2aIngress&version=1.0.0-alpha.16&prerelease
English | 中文版
LabAcacia.A2aIngress
An ASP.NET Core library that exposes a single NPS NWP Action / Complex
Node as a Google Agent-to-Agent (A2A)
server. A2A-speaking peer agents can discover the node via
/.well-known/agent.json and invoke NWP actions through standard JSON-RPC 2.0
without knowing anything about NPS.
- Protocol: A2A v0.2 — JSON-RPC 2.0 over HTTP POST.
- Target: .NET 10, ASP.NET Core.
- NWP spec:
spec/NPS-2-NWP.mdv0.14 (Action Node §7, async lifecycle §7.2,system.task.status/system.task.cancel§7.3).
What it does
| A2A method | NWP call | Notes |
|---|---|---|
GET /.well-known/agent.json |
GET /.nwm + GET /actions on the upstream |
AgentCard advertises one skills[] entry per NWP action. |
tasks/send |
POST /invoke { action_id, params, request_id } |
Sync 200 → Task(completed) with a data artifact. 202 → Task(submitted). |
tasks/get |
POST /invoke { action_id: "system.task.status" } |
Upstream lifecycle pending/running/completed/failed/cancelled maps onto A2A submitted/working/completed/failed/canceled. |
tasks/cancel |
POST /invoke { action_id: "system.task.cancel" } |
Returns Task(canceled) on success. |
tasks/sendSubscribe |
— | Refused with -32004 UnsupportedOperation — streaming is off. |
tasks/pushNotification/* |
— | Refused with -32004 UnsupportedOperation — push is off. |
Skill selection: tasks/send picks the upstream action_id from (in order) —
params.metadata.skillId(+ optionalparams.metadata.params).message.metadata.skillId(+ optionalmessage.metadata.params).- The first
datapart inmessage.parts, keyed byskillId/skill_id/action_id.
Install
dotnet add package LabAcacia.A2aIngress
Quick start
using LabAcacia.NPS.A2aIngress;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRouting();
builder.Services.AddA2aIngress(o =>
{
o.AgentName = "OrdersAgent";
o.AgentDescription = "Create and cancel customer orders.";
o.AgentVersion = "1.0.0";
o.PublicUrl = new Uri("https://bridge.example.com/a2a");
o.Upstream = new A2aUpstream
{
BaseUrl = new Uri("https://action.internal/orders"),
AgentNid = "urn:nps:nid:agent:a2a-ingress",
AuthHeader = "Bearer <service-token>",
};
});
var app = builder.Build();
app.UseRouting();
app.UseEndpoints(e => e.MapA2aIngress()); // GET /.well-known/agent.json, POST /a2a
app.Run();
Point any A2A-compatible client at https://bridge.example.com/.
Configuration
A2aIngressOptions:
| Property | Default | Purpose |
|---|---|---|
AgentName |
NPS A2A Ingress |
AgentCard name. |
AgentDescription |
null (falls back to upstream display_name) |
AgentCard description. |
AgentVersion |
0.1.0 |
AgentCard version. |
PublicUrl |
null (auto-derived from request) |
AgentCard url — the RPC endpoint clients should dispatch to. |
ProviderOrganization |
LabAcacia / INNO LOTUS PTY LTD |
AgentCard provider.organization. |
ProviderUrl |
https://github.com/labacacia/nps |
AgentCard provider.url. |
DocumentationUrl |
null |
AgentCard documentationUrl. |
AuthSchemes |
[] |
AgentCard authentication.schemes (e.g. "bearer"). |
Upstream |
(required) | The single NWP node this ingress fronts. |
A2aUpstream:
| Property | Purpose |
|---|---|
BaseUrl |
Root URL where /.nwm, /actions, /invoke are mounted. |
AgentNid |
Sent as X-NWP-Agent on every upstream call (optional). |
AuthHeader |
Sent verbatim as the Authorization header on every call (optional). |
Error mapping
Standard JSON-RPC (-32700 … -32603) plus A2A application errors:
| Code | Meaning |
|---|---|
-32001 |
Task id unknown — the ingress has no record of that task. |
-32002 |
Upstream refused to cancel the task. |
-32004 |
Method is not implemented (e.g. streaming / push). |
-32010 |
Upstream returned a non-success status during polling. |
Bridge failures appear as the returned Task.status.state = "failed" with an
agent message carrying the upstream HTTP body, rather than as JSON-RPC errors —
this lets A2A clients treat them uniformly with other task failures.
JSON-RPC notifications (requests without id) receive HTTP 204 No Content.
Task-tracking note
The bridge holds an in-process map of {a2a_task_id → upstream_task_id} so that
tasks/get and tasks/cancel can rewrite the request onto the correct upstream
task. Restarting the ingress forgets async tasks in flight. For production
multi-replica deployments, replace the in-memory dictionary with a shared store
(out of scope for v0.1).
Testing
dotnet test tests/LabAcacia.A2aIngress.Tests/LabAcacia.A2aIngress.Tests.csproj
Tests run against a stub HttpMessageHandler — no network required.
Further reading
- A2A Ingress deep dive — 1:1 AgentCard mapping, skill lookup, task state translation, in-memory binding map, replica notes
- Compat ingresses overview — when to pick MCP / A2A / gRPC
License
Apache 2.0. See LICENSE and NOTICE at the repo root.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|