Spring til indhold
DAazure-foundryagent-sharea2a

To agenter, ét team — en Foundry-demo, prompt for prompt

En hel dag på at få en Azure Foundry-agent og min lokale Claude Code til at arbejde som ét team. Hele sessionen indefra — hver prompt, hvert værktøjskald, regningen til sidst.

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.

min prompt1 prompt -> 67 tool calls, 2 brandede decks
9 lines2026-06-08 09:15
I am preparing a demo for for azure foundry tomorrow. Can we make a project in projects folder "azure-foundry-demo" where we will keep everything. I would like to make slides also as we progress , maybe you can follow the structure we have done in the project/vault, where we have content folder with the slide content and we then genrate both a context& and a agentic design system - so we mimic that and we can use the slideshow based on where we are talking I am gonna go though the setup of adding skills and mcp such our agent inside foundry can share stuff with us here over the pks-agent-share project/interface. So please also registere yourself as an agent here so i can send you a few screenshoots.

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/*.mdslides.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.

40 værktøjer48K tok~$9.85

Et par minutter senere kom kvitteringen tilbage fra baggrunds-workflowen:

min promptto skins, 26 PNG'er, selv-verificeret
1 lines2026-06-08 09:35
<task-notification> Dynamic workflow "Build the agentics + context-and slide skins for the Azure Foundry demo, and fact-check/critique the content" completed
27 værktøjer32K tok~$6.56

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.

Samme indhold, to brands13 slides · ét content-folder · klik dig igennem
Cover · Slide 1 af 13
AgenticsAgentics — Cover
Context&Context& — Cover

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.

min prompt4 auth-metoder -> live header-tailing
8 lines2026-06-08 09:47
First thing we want to do is try to connect foundry to our mcp server for share - and to understand we want to go over the 4 authnetication methods they present in foundry: I am gonna use our tunnel here locally so you can pay along and see what they send: https://share--agentic-tunnel.tunnels.agentics.dk:8443/mcp I have send a a screeshoot to you, can you grap that and persist it in our project for documentation. I am gonna try connect
Key-based auth: fra 401 til at se Foundrys token i loggen

That's the Foundry "Add Model Context Protocol tool" dialog — saved. Two things jump out immediately that will matter when you hit Connect:

  1. The credential key says authoriztion — that's a typo (missing a). Foundry sends it as a literal HTTP header, so the server will never see an Authorization header.
  2. The auth dropdown is on Key-based (one of the 4). Let me confirm exactly what our /mcp endpoint 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.

48 værktøjer101K tok~$42

Key-based virkede. Men det rigtigt interessante var de identitetsbundne metoder — OAuth-passthrough mod min egen Keycloak, og Microsoft Entra managed identity:

min promptaudience? -> entra-validator bygget live
1 lines2026-06-08 11:43
i have shared an image with you, what do we add as audience?
Microsoft Entra managed identity: secretless, og audience-feltet er en App Registration vi laver
47 værktøjer91K tok~$38

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.

min prompt1 spørgsmål -> verificeret RBAC-recept
1 lines2026-06-08 14:03
question is, would it be possible with the the agent managed identity from earlier to give it permission to update itself and adding another A2A agent?
Den selvudvidende agent — mekanisk muligt, men verificeret før det blev sagt højt

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.

3 værktøjer17K tok~$5.41
min promptparkér det smarte -> byg det manuelle
13 lines2026-06-08 14:22
lets park it right now - properly not the right part for our demo. Unless we simply do it as a manual step for now. When an agent register it self on the share with an inbox, we could create a dynamic a2a agent card and it can be resolved as you mention on the inbox route. So i can open a claude code session and tell it to register it self. The register call returns the agent card information also (we can add a tool get_agent_card also to retrieve it later). So claude can give me the instructions for Name, A2AEnpoint, Agent Card Path Audience (if we use agent identity) or a token for the key based approach. Then i manually add a agent to foundry and it can be used.
Det rigtige svar på et frontier-spørgsmål: park det, og byg den manuelle version
1 værktøj11K tok~$3.62

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.

min prompt1 grønt lys -> hele A2A-protokollen + 6 tools
1 lines2026-06-08 16:50
yes, lets just do the A2A protocol and we can test exactly what is possible, would just be nice to be able to send notifications back from a task (claude sessions can be somewhat long)
Ét grønt lys, og hele A2A-bridgen skrives, kompilerer rent og bevises end-to-end i en standalone container — fordi Aspire AppHost'en valgte præcis det øjeblik at gå ned.

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} handling message/send (blocking), message/stream (SSE), tasks/get, tasks/resubscribe, tasks/pushNotificationConfig/set. Auth reuses our /mcp resolve — so key-based or the Entra identity both work.
  • New MCP tools: task.list · task.update · task.complete · get_agent_card, and agent.register now returns the Foundry connection block.
  • For your "Claude sessions are long" point: task.update/task.complete buzz the phone via Web Push (pushed: true) — a guaranteed notify-back even if Foundry's client won't take one.
38 værktøjer130K tok~$71

Bygningen stod. Men det var først da Foundry rent faktisk ringede ind, at sandheden om protokollen kom frem:

min prompt1 manglende / -> 30s synkront vindue afsløret
1 lines2026-06-08 18:59
i added a / to the endpoint - anthing coming in?
Et tabt skråstreg i Foundrys endpoint-felt var det eneste, der stod mellem 404 og en levende cross-agent rundtur — og logget dur_ms=30000 afslørede, at Foundry blokerer synkront med et hårdt 30-sekunders loft.
32 værktøjer105K tok~$57

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.

min prompt1 Monitor -> 33 polls/sek afsløret
1 lines2026-06-08 19:09
yes , tail - i will test again
En live-watcher på share-serverens logs afslører Foundrys A2A-klient: 25s blok, så poll-storm.

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."

5 værktøjer21K tok~$11
min promptprotokol-svar + 3-vejs eksperimentplan
29 lines2026-06-08 19:19
what does a2a protocol say about asycn tasks - we dont want to block the agent while we do a long job, so if we cant talk with our agent while its doing get i think its wrong - so can we do a efw experiments. here is the log from the chat: Test the a2a for agentics-live-www and tell it to give a summary of the projevt Copilot said: I tested the A2A connection for agentic-live-www. The remote agent responded successfully twice, so the bridge appears to be working. However, it only acknowledged completion and did not return the actual project summary content. Its responses were: “agentic-live-www here — alive and well. Completed via the A2A bridge.” “agentic-live-www: acknowledged — complete.” So: A2A is reachable, but the remote agent did not provide the requested summary artifact/output. and instad of me testing in their ui, could we just do a small test client here to run our experiment: // dotnet add package Azure.AI.Projects --version 2.0.0-beta.2 using Azure.AI.Projects; using Azure.AI.Projects.Agents; using Azure.AI.Extensions.OpenAI; using Azure.Identity; using OpenAI.Responses; #pragma warning disable OPENAI001 const string endpoint = "https://contextand-cs-foundry.services.ai.azure.com/api/projects/ai-model-credits"; const string agentName = "test001"; const string agentVersion = "2";
Med log-beviset i hånden: hvad A2A faktisk siger om async — og hvorfor blokering er forkert.
5 værktøjer21K tok~$11

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.

Naiv polling (~33 requests/sek) vs. long-poll (én holdt request)

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.

min promptaz login -> .NET driver -> det definitive svar
1 lines2026-06-08 19:44
i have installed azure cli and given my d-pks@****.dk user access as foundry user - can we test if we can run the code with that?

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:

  1. [auth] — mints an https://ai.azure.com/.default token from your az login. This is the proof that Entra/RBAC works (and, by its absence, that no shared key is involved).
  2. [agent] — calls test001 v2 with a joke prompt. If RBAC is wired right (Foundry User on ai-model-credits), you'll see the agent's reply; if the role hasn't propagated yet you'll get a clean 401/403 we can read.
33 værktøjer68K tok~$19

Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:

min prompt1 token -> det afgjorte autentificeringsspørgsmål
1 lines2026-06-08 19:57
i have activated my pim - try again

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) → DefaultAzureCredentialai.azure.com token → 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 waveAzure.AI.Projects 2.0.1 + Azure.AI.Extensions.OpenAI 2.0.0 (GA). The earlier EndpointPipelineData error was purely the mismatched --prerelease Extensions.
12 værktøjer60K tok~$17

Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:

min prompt2 eksperimenter -> protokollen er async, forbrugeren er ikke
1 lines2026-06-08 20:32
can you do a run where you ask it to do a task, then while taht is running in the background continue the conversation with a roundtrip / message with the agent and first after that we complete teh task, so we can illustrate the running in background works pattern

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 held tasks/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."

33 værktøjer77K tok~$21

Med auth-spørgsmålet afgjort kunne jeg endelig køre det eksperiment, der var hele anledningen:

min promptinstrumenter wiren -> ingen task-linkage overhovedet
1 lines2026-06-08 20:51
how does it check in again later for the task? is that a new "task" to check the old task ?
4 værktøjer0K tok

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.

min prompt2 prompts -> mood-set, scrapped, rebuilt as teaching diagrams
5 lines2026-06-08 20:56
Could we do a explainer of this stuff with A2A and Async behavior and our learnings, using images with pks image and gpt-image-2 model? --- love the images - when i said explainer, i was thinking more like the onces we did on the photogrammatr where we explained how it worked so people understood it after :D this is nice graphics for sure but they dont explain what we learned with the A2A protocol
De første billeder var for pæne. Anden runde skulle undervise.

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).

26 værktøjer47K tok~$23
min promptspec-tjek + wire-trace -> ærlig to-sidet attribution
5 lines2026-06-08 21:21
can we grap the actually requests and payloads out from the experiment we ran so we also have that to show when explaining foundry is not sending taskid/contextid. Is these part of the A2A specification? --- do we thin its foundry not implementing it in their part, or is is it our agent not doing it?
Bevis frem for påstand — og en ærlig erkendelse af vores egen halvdel.

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 contextId to echo. That's a client-side omission in a2a_preview.
  • But in full honesty, our demo bridge has the matching gap: even if Foundry did echo a contextId, our createTask ignores 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.

30 værktøjer47K tok~$23

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:

A2A er async-first: message/send returnerer en Task med det samme

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

Foundry sender ikke taskId/contextId videre mellem turene

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.

min promptagent-share channel
1 lines2026-06-08 22:16
i want to test the channels thing
Vores binary ER kanalen — ikke en Bun-sidecar
24 værktøjer150K tok~$80

Næste morgen, ud på de små timer, kom finalen — og den store polish, der gør demoen til at huske-ingenting:

min promptagent-share install channel
9 lines2026-06-09 03:28
one of the things i try to do for my agentic developemnt is not to have to remember commands. fair that i have to do agent-share login the first time, but to not remember the remaining commands, would it make sense that after claude --dangerously-load-development-channels server:agent-share --dangerously-skip-permissions it has the normal mcp register tools so i within the session is doing "Register on agent-share" and it gives me the card info inside the session also (not a replacement for the other flow, its good to a have a way to use an existing inbox) but it makes it easier to demo? and also if i share something to the inbox it also becomes a task on the channel, so both the A2A and sharing to the agent is processed?
Foundry-finalen og "jeg vil ikke huske kommandoer"

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 MCP agent.register sets the name), so I'll add a small POST /api/agent/identity and expose register + get_agent_card + list tools on the channel.
  • Shares → channel: every to_agent share already fires OnShare; 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/list shows all five, and calling get_agent_card returned 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/channelcontent:"remember to review the PR", kind:"text", shareId:…, and mark_received worked. 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.

18 værktøjer120K tok~$51

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:

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:

hele sessionen
19t 5m2026-06-08 → 09
est. pris
$492
værktøjskald
485
mine prompts
60
model
Claude Opus 4.8
1.1M tok genereret229M behandlet · inkl. cache
estimeret pris pr. time
09:00
$31.57103
10:00
$9.7312
11:00
$36.9441
·
pause
13:00
$16.735
14:00
$10.135
·
pause
16:00
$30.9315
17:00
$54.7635
18:00
$30.5914
19:00
$45.7235
20:00
$48.2083
21:00
$45.4656
22:00
$53.8043
·
pause
·
pause
·
pause
·
pause
03:00
$62.7331
04:00
$14.657
mest brugte værktøjer
Bash
156
Edit
125
Read
91
Write
47
aspire (logs/cmd)
27

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.