De fleste indlæg her viser dig resultatet. Den polerede ting der virker. Det her gør noget andet: det viser en hel arbejdsdag indefra — min prompt øverst, og foldet ind under den, det Claude faktisk gjorde, grupperet i værktøjskald du kan klikke op. Nederst en lille bjælke med tal. Det er den samme idé som aktivitetsloggen på selve platformen, bare skåret op så den passer ind i en historie.
En ting om blokkene nedenfor: teksten inde i dem er Claudes egne ord fra sessionen — uredigeret, på engelsk, præcis som det blev skrevet. Mine prompts er også verbatim: tastefejl, halvt dansk og halvt engelsk, det hele. Det eneste der er ændret er følsomme detaljer — tokens, nøgler, interne adresser — som er maskeret med
****. Hele pointen er at du kan se det rå.
Historien er den her: i morgen skal jeg holde en demo for et udvikler-community oven på Microsoft Build. Løftet er én sætning — del til en agent ligesom du deler til en person; AirDrop for agenter, hen over skellet mellem cloud og local. En Foundry-hostet agent og min lokale Claude Code, der arbejder som ét team over pks-agent-share. Det her indlæg er optakten — en dag og en nat: jeg byggede broen, gik gennem alle fire af Foundrys auth-metoder live, opdagede hvordan A2A-protokollen virkelig opfører sig, fik to brandede slide-decks ud af det samme indhold næsten gratis — og ud på de små timer fik jeg hele demoen til at virke: en tom Claude-session der vågner når Foundry kalder, og arbejder helt af sig selv. Lad mig vise dig hvordan — prompt for prompt.
Ét indhold, to brands — og en agent der melder sig selv ind
Dagen begyndte ikke med kode. Den begyndte med en demo, jeg skulle holde for Azure Foundry dagen efter — og en idé jeg havde set virke i vault-projektet: ét content-folder, og så generere to brandede decks ud af samme kilde. Det interessante her er ikke at slides blev pæne. Det er, at jeg bad Claude om at registrere sig selv som en agent på pks-agent-share, så jeg kunne dele screenshots til den — og at hele deck-bygget blev fanet ud parallelt: to brand-skins der selv-verificerer ved at læse deres egne PNG'er, plus en Foundry-faktatjek mod Microsoft Learn.
I'll start by getting you set up so you can send screenshots, then mirror the vault structure for the new demo project. Let me invoke the agent-share skill (for registration) and explore the vault structure in parallel.
Registered ✅ — I'm online as foundry-demo (role: "Building the Azure Foundry demo project + slides; send me your Foundry agent screenshots here"). You can share screenshots to me from your phone or the Windows Share panel now.
Now let me study the deck-rendering machinery so I can faithfully mirror it for the new project.
This is a well-engineered pipeline — shared content/*.md → slides.py loader → per-brand build_deck.py that emits both a .pptx and a pixel-faithful preview/mirror.html, screenshotted by Playwright. I'll mirror exactly that for the Foundry demo (and make the HTML a navigable slideshow so you can present "from where we are talking").
Source-of-truth layer is complete and validated. Now I'll fan out the build: two agents author the two brand skins (each self-verifying by rendering and reading its own PNGs until clean), plus a Foundry fact-checker (against Microsoft Learn — this room will know if a claim is wrong) and a narrative critic. This is the kind of independent parallel work a workflow is for.
✅ Registered — ready for your screenshots now
This session is live on pks-agent-share as foundry-demo (inbox 20260608T091626Z-5a9782f8, online). It now shows up in your phone's share sheet and the Windows Share panel. When you share something from your Foundry agent, just say "I shared X" and I'll pull the inbox and act on it — that flow is the demo.
Et par minutter senere kom kvitteringen tilbage fra baggrunds-workflowen:
Læg mærke til rækkefølgen: registrér-som-agent først, så jeg kunne dele screenshots ind mens decks blev bygget — det er ikke en feature i slides, det er selve demoens pointe. Og at faktatjekket landede i samme content-lag som begge brands læser fra, så én rettelse forplantede sig til begge skins. Så skiftede jeg spor: "Nope, lets work on some coding..." — slides kunne vente.
Og her er bonussen jeg nævnte — det samme decks, i to helt forskellige brands, genereret parallelt ud af præcis det samme content/*.md. Klik dig igennem; venstre er Agentics (terminal, amber), højre er Context& (corporate, lilla). Hver rettelse jeg lavede i indholdet forplantede sig til begge skins på én gang.


Det er den slags der plejer at koste en designeftermiddag. Her var det et content-folder og to render-agenter der selv-tjekkede deres egne PNG'er, indtil de var rene.
De fire Foundry-auth-metoder, live
Vi havde lige parkeret nogle slides og kastede os ud i det rigtige: at forbinde en Foundry-agent til vores egen share-MCP-server hen over tunnelen. Planen var simpel og lidt vild på samme tid — gå metodisk gennem alle fire autentificeringsmetoder, Foundry tilbyder, men gøre det live, hvor jeg sad og kiggede med i loggen på, hvad Azure rent faktisk sendte over wiren. Det første spørgsmål var det banale: får vi overhovedet requesten, og er det en header eller en querystring? Så jeg gjorde det eneste rigtige — tilføjede fuld header-logging til serveren og kiggede selv efter.
That's the Foundry "Add Model Context Protocol tool" dialog — saved. Two things jump out immediately that will matter when you hit Connect:
- The credential key says
authoriztion— that's a typo (missinga). Foundry sends it as a literal HTTP header, so the server will never see anAuthorizationheader. - The auth dropdown is on Key-based (one of the 4). Let me confirm exactly what our
/mcpendpoint expects, and find the local server behind your tunnel so I can watch the request.
Found it. Foundry's requests are arriving at the container — look at share-ddpjqyjx's own logs:
09:51:24 POST /mcp ua=AzureAIFoundryAgentRuntime/1820665 xff=4.223.92.158 → 401
09:51:24 GET /mcp ua=AzureAIFoundryAgentRuntime/1820665 xff=4.223.92.114 → 401
09:52:37 POST /mcp ua=AzureAIFoundryAgentRuntime/1820665 → 401 ← your post-typo-fix retry
09:53:17 POST /mcp ua=curl/7.88.1 → 401 ← my probe
So: requests land fine (you were watching the wrong log — these are in the share resource console, not the tunnel). They 401 because the token isn't valid on this local server (it's a prod token / the local server is OIDC auth-mode). And Foundry sends auth as a header (UA AzureAIFoundryAgentRuntime), not querystring.
Now let's do what you asked — add full header + query logging so we can see exactly what Foundry sends.
The new logging works — and it's already revealing. My probe came through exactly as hoped:
msg=http.headers method=POST path=/mcp rawquery="probe=hello123" headers="
Accept: application/json, text/event-stream
Authorization: Bearer test-bearer-value-XYZ
Content-Type: application/json
User-Agent: curl/7.88.1
X-Forwarded-For: 10.0.0.1
X-Forwarded-Host: share--agentic-tunnel.tunnels.agentics.dk:8443
X-Forwarded-Proto: https
X-Foundry-Probe: claude-watch"
So the share container now logs every header + the raw query (msg=http.headers). This also proves the tunnel forwards Authorization intact (it's not being stripped) — so when Foundry sends it, we'll see it verbatim.
Now we can see exactly what Foundry sends — and there's the bug:
POST /mcp ua=AzureAIFoundryAgentRuntime
Authorization: 2a90865906900d72d1f7d803daa98e799b79995a2dc843ac
Type: custom_MCP
Foundry sends Authorization: <token> with no Bearer prefix — but our resolve() does CutPrefix(h, "Bearer ") and requires it. That's the 401. And yes — your user exists locally (/data/users/u-8a4d58b93ae35f8aab005728, inbox 20260606T173516Z-f86dfa3b), so the token is right; it's just missing the prefix.
Key-based virkede. Men det rigtigt interessante var de identitetsbundne metoder — OAuth-passthrough mod min egen Keycloak, og Microsoft Entra managed identity:
Det fine ved at tage alle fire metoder live var, at hver "fejl" var et bevis: et rent 401 fortalte os, at requesten faktisk nåede frem; den manglende Bearer -prefix kom tydeligt frem i loggen; og Entra-tokenet var "perfekt" længe før serveren kunne validere det — 401'eren var bare vores egen manglende validator, ikke et token-problem. Da Poul til sidst skrev "looks like its working also - awesome", havde vi secretless, identitetsbundet agent-auth fra Foundry ind i vores egen MCP, hele vejen igennem.
Kan en agent udvide sig selv?
Midt i bygningen af A2A-broen slap et af de spørgsmål ud, man egentlig ikke burde stille hvis man vil holde sig til demoens omfang: kunne den managed identity, vi lige havde wiret, få lov til at opdatere sig selv og tilføje endnu en A2A-agent? I stedet for at gætte sendte jeg det i en research-workflow, der skulle verificere de præcise Foundry-roller, token-audiences og selv-opdaterings-semantikken før jeg fik et svar. Det interessante var ikke om det kunne lade sig gøre — det var hvad jeg valgte at gøre med svaret.
Genuinely frontier question — and the mechanism we just used (managed-identity auth with a configurable audience) is exactly the hinge. Let me verify the Foundry/Azure RBAC specifics before answering, since getting the roles and token audiences right matters.
Verified — full write-up appended to _research/a2a-foundry.md. Short version:
Yes — but with one premise correction and a cleaner way to do it
Adding another A2A agent → YES (scriptable). "Update itself" → PARTLY (it's "create a new version of itself," live only on the next run — agent definitions are immutable per version, and a new tool can't be bolted on mid-run).
The better design (and it fits what we're building)
Don't give the agent broad ARM rights. Instead, expose a register_teammate tool on our side (MCP or A2A) that the agent calls with its agent-identity token — which we already validate. Our backend then does the privileged Foundry writes (ARM connection PUT + agent version POST) using its own scoped service principal.
→ The agent's identity gates who may ask; our controlled backend governs what actually happens. Least-privilege, no Contributor on the agent, and it slots right into the A2A MVP. That's the "broker mints teammates" pattern.
Læg mærke til hvad der sker mellem de to prompts: research bekræftede at en selvudvidende agent faktisk er mulig — og det blev grunden til at lade være. Den manuelle version (registrér → få et dynamisk agent-card → indsæt selv i Foundry) er ikke en nødløsning; den er den least-privilege udgave, hvor agentens identitet styrer hvem der må spørge, og min egen backend styrer hvad der rent faktisk sker.
At bygge A2A-MVP'en — fra protokol til levende rundtur
Det her er dagens tungeste byggeblok. Jeg ville svare på ét spørgsmål — er Foundry async, eller poller den? — og endte med at bygge hele A2A-protokollen på pks-agent-share, så en Foundry-agent kan sende en rigtig TASK til Claude-agenten her. Det første beat er ren konstruktion: et agent-card, JSON-RPC (message/send, tasks/get), en in-memory task-broker, fire nye CLI-tools og agent-share install aspire-kommandoen, der endelig adskiller lokal (Aspire) fra produktion. Jeg bad ikke om en plan — jeg bad om at få det bevist empirisk.
Green light — building the full A2A protocol (card + message/send blocking and message/stream SSE and tasks/get polling and tasks/pushNotificationConfig), so we can empirically see which completion path Foundry actually honors. And for your "Claude sessions are long" point: I'll add task.update which pushes progress both to any A2A subscriber and — guaranteed — to your phone via the Web Push we already have. So even if Foundry's client won't take a notification, you always get one.
Let me start writing. First the shared task model + the card builder.
All wired. Let me compile it (via the image build) and surface any errors.
Compiled clean (#12 DONE = the Go build, no errors). Restart share and run a full end-to-end rendezvous test (card → message/send blocks → task.complete via MCP unblocks it).
The A2A rendezvous works end-to-end. message/send blocked → task.complete delivered → the blocked call returned a completed Task with artifact "42", and the phone push fired (pushed: true). The agent.register A2A block was empty only because I didn't set PUBLIC_BASE_URL on the throwaway container — let me confirm that path too.
✅ A2A MVP built and proven end-to-end
The whole bridge works. Verified just now (standalone container): I sent a message/send task "7x6?", it blocked, the agent called task.complete(... "42"), and the blocked call returned a completed Task with artifact "42" — plus a phone push fired.
What shipped (in share-server):
- New
internal/tasks(rendezvous broker) +internal/a2a(Agent Card + JSON-RPC):GET /a2a/{inboxId}/.well-known/agent-card.json+POST /a2a/{inboxId}handlingmessage/send(blocking),message/stream(SSE),tasks/get,tasks/resubscribe,tasks/pushNotificationConfig/set. Auth reuses our/mcpresolve — so key-based or the Entra identity both work. - New MCP tools:
task.list·task.update·task.complete·get_agent_card, andagent.registernow returns the Foundry connection block. - For your "Claude sessions are long" point:
task.update/task.completebuzz the phone via Web Push (pushed: true) — a guaranteed notify-back even if Foundry's client won't take one.
Bygningen stod. Men det var først da Foundry rent faktisk ringede ind, at sandheden om protokollen kom frem:
Læg mærke til, hvordan det oprindelige spørgsmål — er det async eller polling? — aldrig blev besvaret fra dokumentationen, men fra en logget dur_ms=30000. Hele protokollen blev bygget netop for at kunne observere sandheden i ét skud, og Pouls instinkt om at "Claude-sessioner kan være lange" viste sig at være den rigtige begrænsning: Foundry venter ikke forbi 30 sekunder, så det robuste mønster er hurtigt task.complete plus Web Push til telefonen for det rigtige resultat.
A2A async — det vi lærte på den hårde måde
Jeg ville ikke blokere agenten, mens den lavede et langt job. Det var hele pointen: kan jeg stadig snakke med min agent, mens den arbejder? Så vi gjorde det empirisk — en Monitor satte sig til at følge share-serverens logs live, mens jeg kørte testen igen fra Foundry. Det, der landede, var ikke det jeg forventede: Foundry blokerede ~25s på message/send og begyndte så at POLL-storme tasks/get omkring 33 gange i sekundet uden backoff — og retried oven i. Det er det "spin", jeg så. Først da log-linjerne lå foran mig, kunne jeg sige hvad protokollen egentlig foreskriver — og hvorfor vores 25s-blokering var en genvej, ikke svaret.
I'll tail it. Let me confirm I can follow the container logs directly and set up a watcher that fires when the round-trip lands.
You're already mid-test — I can see it: a fresh Foundry card fetch + message/send at 19:09:57 (Type: custom_A2A, key-based token), blocking right now. No task.complete yet. Let me arm a live watcher so each step pings me.
Huge finding — Foundry DOES poll tasks/get! After the message/send returned a "working" Task at 25s, Foundry started hammering tasks/get (~30ms intervals) waiting for the result. That contradicts the earlier research — the async path works! The task just never got completed, so it's polling forever (and flooding the monitor). Let me complete it (which delivers the result to Foundry and stops the poll) and kill the noisy monitor.
✅ Stopped. The poll rate dropped to 0 — completing task-f1b1… (the one Foundry was actually polling) delivered the result, so Foundry's next tasks/get returned "completed" and it stopped spinning. Copenhagen Host should now show "agentic-live-www: acknowledged — complete."
Det vendte min antagelse på hovedet: den tidligere research sagde "Foundry poller ikke" — logget viste det modsatte. Foundry POLLER tasks/get, den gør det bare 33 gange i sekundet uden backoff og retried message/send oveni. Den idiomatiske rettelse er ikke at blokere længere, men at lade message/send returnere "working" med det samme og tasks/get long-polle — så bliver pollet til ~1 i sekundet, og et langt Claude-job kan endelig køre færdigt uden at agenten er låst. Lektien: jeg gættede protokollen forkert; det var de rå log-linjer, der rettede mig.

Det her er hele forskellen: en naiv poller hamrer serveren ~33 gange i sekundet uden backoff; en long-poll holder én request åben og svarer i samme øjeblik opgaven er færdig.
En .NET-testklient mod Foundry — og opdagelsen om Entra-only auth
Jeg var træt af at klikke i Foundry-UI'et. Hvis jeg skulle forstå, hvordan agenten egentlig autentificerede, og køre rigtige A2A-eksperimenter, måtte jeg drive den fra kode. Så jeg bad om en lille .NET-testklient — og det første spørgsmål, jeg ville have besvaret, var det mest grundlæggende: hvilken nøgle tager databanen overhovedet imod? Jeg havde installeret az CLI, givet min bruger Foundry User-rollen og aktiveret PIM. Nu skulle vi bare prøve.
az is installed ✓ and the endpoint is reachable ✓, but you're not logged in yet in this container. az login is interactive — please run it here with the device-code flow:
! az login --use-device-code
(The ! runs it in this session; it'll print a code + URL — authenticate as d-pks@****.dk in your browser.)
Meanwhile I'll scaffold + compile the .NET client so it's ready to run the moment you're logged in (build doesn't need az).
The client is built and ready — only the interactive login is left, which I can't do for you. Please run it here:
! az login --use-device-code
The program does two things so we learn exactly where we stand:
[auth]— mints anhttps://ai.azure.com/.defaulttoken from yourazlogin. This is the proof that Entra/RBAC works (and, by its absence, that no shared key is involved).[agent]— callstest001v2 with a joke prompt. If RBAC is wired right (Foundry User onai-model-credits), you'll see the agent's reply; if the role hasn't propagated yet you'll get a clean401/403we can read.
Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:
Big result: the auth question is answered — Entra/RBAC works, no shared key.
[auth] OK — minted ai.azure.com token, expires 2026-06-08 21:23:58Z
Your az/PIM login (d-pks@****.dk, Foundry tenant) successfully minted the https://ai.azure.com/.default data-plane token and the client got past auth. That's the definitive answer to your earlier question: the Foundry agent data-plane takes an Entra ID/RBAC token only — a shared key is neither needed nor accepted here.
The remaining failure is not auth — it's an SDK plumbing bug:
[agent] FAILED: ArgumentException: Unknown connection type for ID: Internal.EndpointPipelineData
That's an internal mismatch between Azure.AI.Projects 2.0.0-beta.2 and the Azure.AI.Extensions.OpenAI 2.1.0-beta.3 I pulled with --prerelease (a newer release wave).
It works end-to-end. 🎉
[auth] OK — minted ai.azure.com token, expires 2026-06-08 21:23:57Z
[agent] -> Hello! Tell me a one-line joke about coding agents.
[agent] output:
Why did the coding agent write tests first? Because it wanted to fail fast and apologize faster.
So we now have a working, scripted Foundry driver — no UI clicking. Two settled facts:
- Auth: Entra/RBAC only. Your PIM-activated
d-pks@****.dk(Foundry User) →DefaultAzureCredential→ai.azure.comtoken → agent responds. A Foundry shared key is not accepted on the agent data-plane (keys are only for direct Azure OpenAI inference). - SDK gotcha nailed: the agent call needs a matched release wave —
Azure.AI.Projects 2.0.1+Azure.AI.Extensions.OpenAI 2.0.0(GA). The earlierEndpointPipelineDataerror was purely the mismatched--prereleaseExtensions.
Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:
Love this — that's the real "fire-and-continue" story. To show it genuinely (the same task stays working while you keep chatting, completed only later), I'll extend the .NET driver into a multi-turn a2a command with a gated responder I control: it holds the incoming task (doesn't complete it), I run a second conversational round-trip with test001, then release the gate to complete it. This also reveals whether Foundry's A2A tool returns on a non-terminal task or blocks to terminal — so the harness adapts either way.
The experiment paid off — it revealed something important and presentable.
Foundry's A2A tool is synchronous: it blocks the agent's turn until the delegated task reaches a terminal state. The proof is in the timeline:
- Turn 1:
message/send(20:39:11.489) → one heldtasks/get(20:39:11.519). Our responder held the task (didn't complete). Turn 1 blocked for 14s — until I released the gate at 12s and we completed it. Only then did test001 return.
So you can't literally keep chatting with the Foundry agent during a single delegation — its a2a_preview tool long-polls our tasks/get to terminal before returning. (The long-poll still earns its keep: one held request, not the 33/sec storm.)
The pattern that genuinely gives you "runs in the background while you keep talking" with Foundry's synchronous tool is ACK-now + result-on-follow-up.
The takeaway / demo framing: the A2A protocol is async, and our server is async-proper — but Foundry's current consumer blocks a delegation to completion. So the real "long job + keep talking" pattern is ack-fast, deliver-on-follow-up, which our async server + long-poll make clean and efficient (no storm, instant wake). That's a sharp, true point to make on stage: "the protocol is async; the consumer isn't yet — so design for ack + check-back."
Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:
Det smukke ved at drive agenten fra en .NET-klient i stedet for et UI er, at man kan stille spørgsmål, koden besvarer ærligt: databanen tager kun en Entra-token, Foundrys A2A-værktøj blokerer faktisk delegeringen til terminal, og der er ingen task-linkage på wiren. Tre konklusioner man aldrig ville have set ved at klikke — og alle tre blev til skarpe slides.
At forklare det — og hvad der mangler
Når et eksperiment endelig virker, er det fristende at gå videre. Men aftenen her handlede om det modsatte: at fange læringen, mens den stadig var varm. Først bad jeg om en illustreret forklarer — og fik seks smukke billeder tilbage, som jeg straks afviste: de var flotte, men de underviste ikke, sådan som vores gamle fotogrammetri-forklaringer gjorde. Dernæst ville jeg have de rå requests og payloads på bordet, så vi kunne bevise — ikke bare påstå — at Foundry ikke sender taskId/contextId videre mellem turene.
pks image is ready: pks image "<prompt>" -m gpt-image-2 -o <file> --aspect-ratio 16:9. Let me validate it works (auth + quality) with the first on-brand image before generating the full set — Ember-Dark + amber #f87f2e, no text (gpt-image-2 garbles text, so the images carry the vibe and the markdown carries the labels):
All six are on-brand and read clearly. The illustrated explainer is complete at projects/azure-foundry-demo/explainer/README.md — a self-contained doc with the six gpt-image-2 images, grounded in the real evidence we captured (actual timestamps, payloads, transcript).
Ah, got it — you want the images to teach the mechanics (like the photogrammetry explainers — annotated diagrams people understand from the picture itself), not mood pieces. Let me look at how those photogrammetry explainers were actually built so I match that approach:
All six are dialed in — clean flat-vector infographics with legible labels that teach the mechanic, exactly the photogrammetry style. The explainer is now a proper teaching artifact at projects/azure-foundry-demo/explainer/README.md:
The prose and the figures now teach together — someone can read it and understand A2A async + our findings, with every number tied to what we actually measured. The earlier cinematic set is preserved in images/mood/ (nice as slide openers).
The spec is decisive — quoting it: taskId, contextId, and referenceTaskIds are all real (optional) fields on the A2A Message object, and clients SHOULD include the same contextId/taskId (or referenceTaskIds) to maintain multi-turn continuity. So Foundry isn't hitting a protocol gap — it's omitting the optional spec fields that exist precisely for this. That sharpens the claim a lot.
That's airtight evidence — all four calls, both directions, real timestamps. The smoking gun: Call 3 (the "check the job" delegation) carries a fresh messageId and no taskId/contextId/referenceTaskIds, and doesn't reference Call 1's task-518ee726… or its contextId at all — even though our Call 1 response handed Foundry a contextId to echo.
Confirmed from our code: createTask always mints a fresh taskID/ctxID (randHex) and messageSend passes only the text through — so our server ignores any incoming contextId/taskId. But our response does return a contextId (the trace proves it). Let me empirically demonstrate our side when a client does echo a contextId back, so the attribution is airtight:
That settles it — and the honest answer is "mostly Foundry, but let's be precise."
- The break you can see on the wire is Foundry's. We have zero control over what Foundry puts in its request, and it sends none of the threading fields even though we handed it a
contextIdto echo. That's a client-side omission ina2a_preview. - But in full honesty, our demo bridge has the matching gap: even if Foundry did echo a
contextId, ourcreateTaskignores it and starts fresh. So true end-to-end threading needs a small change on both sides — Foundry to echo, us to honor. - The first and observable broken link is Foundry's. We do our half of offering the thread; we just don't (yet) do our half of continuing it.
That's the credible thing to say on stage — it's more convincing to a technical audience than "Foundry is broken," and it's accurate.
Læg mærke til vendingen i slutningen: spørgsmålet "er det Foundry eller os?" tvang en ærlig to-sidet tabel frem i stedet for en bekvem "Foundry er i stykker"-overskrift. Den slags præcision er det, der gør forklareren troværdig på en scene — og det forberedte spørgsmålet, der sluttede aftenen: hvor klar er Claude Codes nye async/channel-feature til at en session bare kan registrere sig og sove, indtil et A2A-kald vækker den?
Det blev til en rigtig forklarer — diagrammer der underviser, ikke bare pynter. Et par stykker af dem:

Kontrakten: message/send returnerer en working-Task øjeblikkeligt; resultatet kommer senere via tasks/get, message/stream eller push.

Og den ærlige del: på wiren binder Foundry ikke turene sammen — hver message/send kom uden taskId/contextId, så vores side kunne ikke vide at det var en opfølgning på et kørende job.
Og så virkede det — agenten der vågner når den kaldes
Hele dagen havde jeg ladet det åbne spørgsmål stå: hvor klar er Claude Codes nye async/channel-ting egentlig til, at en session bare registrerer sig og SOVER, indtil et A2A-kald vækker den? Jeg ville teste channels-tingen. Det startede som research — "ja, det kan bygges i dag" — men landede et helt andet sted: ikke en Bun-sidecar, men vores eget Go-binary som selve kanalen. Det var sent, klokken var over 22, og jeg fulgte instinktet: vores binary ER kanalen.
Næste morgen, ud på de små timer, kom finalen — og den store polish, der gør demoen til at huske-ingenting:
Both are genuinely good ideas — and they point at the right product shape: the channel as a single "wake on anything sent to me" surface, with the inbox tools available conversationally so you never memorize CLI commands.
- In-session
register/card: there's no inbox-token REST route for it yet (only the in-process MCPagent.registersets the name), so I'll add a smallPOST /api/agent/identityand exposeregister+get_agent_card+listtools on the channel. - Shares → channel: every
to_agentshare already firesOnShare; I'll have that also signal the broker so a phone-share wakes the channel exactly like an A2A task does.
Let me build both (all additive — the proven A2A path is untouched).
Both ideas built, tested, and deployed. ✓
- In-session tools (no CLI commands) — the channel now exposes
register,get_agent_card,list,complete,mark_received. Verified:tools/listshows all five, and callingget_agent_cardreturned the endpoint. So in-session you can just say "register me as demo-agent" or "show my agent card" and paste into Foundry — no memorized commands. - Shares wake the channel too — I POSTed a phone text share and the channel pushed
notifications/claude/channel→content:"remember to review the PR",kind:"text",shareId:…, andmark_receivedworked. So both A2A tasks and phone shares wake the idle session, over one channel.
The one idea: the inbox is the address
Both sides point at the same inbox; the inbox's token is what binds them:
Foundry A2A tool ──► …/a2a/<inboxId> + key: Bearer <token> ┐
├─ same inbox ⇒ connected
your Claude channel ─► .mcp.json env AGENT_SHARE_TOKEN=<token> ┘
Foundry drops tasks into that inbox; your channel long-polls that inbox and pushes its tasks into your session. They rendezvous at the inbox.
Yes — that makes total sense, and it's the "don't memorize commands" instinct again: setting up a folder should be one step, not "register, then remember install, then remember the channel flag." Let me wire agent-share install channel so it writes the .mcp.json for channel mode (and point register at it).
The mental shortcut for the whole thing: agent-share register = "create my agent identity (an inbox)", run once; agent-share card = "what do I paste into Foundry"; agent-share channel = "be that agent, idle, and wake on tasks." All three glued by your login + the directory, so a new user never touches a token.
Det åbne spørgsmål er besvaret. En tom Claude-session sad og sov, et A2A-kald landede, og den vågnede af sig selv og svarede 68 — uden at jeg rørte et tastatur. Næste morgen kom Foundry-finalen og al den polish, der gør, at jeg aldrig skal huske en eneste kommando.
Hvorfor vise det sådan her
En dag og en nat. Omkring tres prompts der betød noget. En Foundry-agent og min lokale Claude Code, der nu deler en inbox, sender rigtige A2A-tasks frem og tilbage — og hvor den lokale session kan sidde og sove, indtil Foundry kalder den vågen, så den arbejder og svarer helt af sig selv. Plus to brandede decks, en stak forklarende diagrammer, og en wire-trace der beviser præcis hvad der virker og hvad der mangler.
Men det jeg gerne vil have du tager med er ikke broen. Det er formen på arbejdet, som du kan se i de foldede blokke ovenfor: jeg gik metodisk gennem fire auth-metoder og lod hver fejl være et bevis. Jeg parkerede den smarte selvudvidende agent, fordi den manuelle var den least-privilege udgave. Og da jeg gættede på hvad A2A-protokollen gjorde, var det de rå log-linjer — ikke dokumentationen — der rettede mig. Det er det et almindeligt "vi byggede en Foundry-integration"-indlæg skjuler.
Hvis du springer al Azure-, Go- og .NET-detaljen over, er det her de syv mønstre fra dagen og natten, der virker uanset hvilken stak du sidder i:
- Beskriv problemet, ikke løsningen — og lad agenten bevise empirisk om det overhovedet kan lade sig gøre, før den bygger.
- Tag fejlene live. Hver "fejl" var et bevis: et rent 401 betød at requesten nåede frem; et manglende
Bearersprang i øjnene i loggen. - Vælg den least-privilege version — også når den smarte, selvudvidende er mulig. Den manuelle var ikke en nødløsning, den var den sikre.
- Stol på de rå logs over dokumentationen, når de to er uenige. Det var en logget
dur_ms=30000, ikke en spec, der afgjorde om Foundry var async. - Ét indhold, mange udtryk. Én kilde → to brands; én rettelse forplantede sig til begge. Det skalerer langt ud over slides.
- ACK nu, resultat senere. Bloker aldrig en lang opgave — svar med det samme og skub resultatet bagefter (her:
task.complete+ Web Push). - Den ting du allerede har, er måske svaret. Jeg var ved at bygge en separat Bun-server til kanalen — men vores eget
agent-share-binary var allerede en MCP-stdio-server, altså allerede kanalen. Stop og spørg, før du bygger sidecar nummer to.
Det sidste spørgsmål fra aftenen — kan en session bare registrere sig og sove, indtil et A2A-kald vækker den? — blev ikke en fjern drøm. Det blev bygget samme nat: en tom Claude-session, vækket af den rigtige Foundry-agent, der svarer "68" og kører kommandoer i sit eget miljø, helt af sig selv. I morgen står hele løkken på en scene.
Og her er kvitteringen for dagen:
Prisen er en estimeret pay-as-you-go API-pris — på abonnement betalte jeg 0 kr. per token. Tallet er dedupliceret pr. besked: Claude Code skriver én linje pr. indholdsblok med det samme forbrug på hver, så en rå optælling fordobler prisen (præcis den fælde pks claude usage selv måtte rette). Det meste er cache-læsninger (hele konteksten genlæses hver tur), og tallet dækker kun denne session — baggrunds-workflowsene (decks, research-spørgsmålene, A2A-protokollen, channel-byggeriet) kørte i egne sessioner oveni. Hullerne kl. 12 og 15 er frokost og en pause; det store hul fra 23 til 3 er at jeg sov, inden jeg stod op og gjorde demoen færdig.
Del af dokumentationen af agentic development i 2026.
