{"id":624,"date":"2026-06-15T21:08:01","date_gmt":"2026-06-15T21:08:01","guid":{"rendered":"https:\/\/codingwithramin.com\/?p=624"},"modified":"2026-06-15T21:08:02","modified_gmt":"2026-06-15T21:08:02","slug":"meet-work-iq-the-intelligence-behind-copilot-now-an-api-you-can-build-on","status":"publish","type":"post","link":"https:\/\/codingwithramin.com\/?p=624","title":{"rendered":"Meet Work IQ: The Intelligence Behind Copilot, Now an API You Can Build On"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If you&#8217;ve built an enterprise agent that needs to understand what&#8217;s actually happening inside an organization \u2014 who&#8217;s working on what, what was decided in last week&#8217;s meeting, which document is the latest version of the proposal \u2014 you already know the hard part isn&#8217;t the model. It&#8217;s the context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve spent a good chunk of the last year on exactly this problem. In my <a href=\"https:\/\/codingwithramin.com\">SharePoint agents series<\/a> I grounded an agent in SharePoint content, and more recently I added <a href=\"https:\/\/codingwithramin.com\/?p=592\">long-term memory to Foundry agents<\/a> so they&#8217;d stop forgetting everything between turns. Both worked. Both also meant I was building and maintaining plumbing: connectors, indexing, retrieval, and \u2014 the part nobody enjoys \u2014 permission trimming, so the agent never surfaces something the user isn&#8217;t allowed to see.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Work IQ is Microsoft&#8217;s answer to that plumbing. Microsoft says the <strong>Work IQ APIs<\/strong> go generally available on <strong>June 16, 2026<\/strong>, and honestly it&#8217;s the missing piece I kept wishing Microsoft would expose. This post is the first in a short series on building with it. In this one I&#8217;ll explain what Work IQ actually is, how it&#8217;s different from the approaches you might be using today, and make a first grounded call from C#. Later posts will build a proper agent with the A2A SDK, wire Work IQ in as MCP tools, and look at long-running agents with Workspaces.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>The problem, stated plainly<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Say you want an agent that can answer: <em>&#8220;<strong>Catch me up on the Contoso migration \u2014 what&#8217;s the latest, who owns it, and what did we agree in the last review?<\/strong>&#8220;<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To answer that well, the agent needs to pull from email, Teams chats, meeting transcripts, files in SharePoint and OneDrive, and the org chart, then reason across all of it. The usual approach looks something like this:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Stand up connectors to each source.<\/li>\n\n\n\n<li>Extract and index the content into a vector store.<\/li>\n\n\n\n<li>Keep that index fresh as content changes.<\/li>\n\n\n\n<li>Re-implement Microsoft 365&#8217;s permission model so a user never sees content they don&#8217;t have rights to.<\/li>\n\n\n\n<li>Stitch the retrieved chunks into a prompt and hope your ranking is good enough.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Steps 3 and 4 are where a lot of these projects start to fall apart. Permission trimming is especially nasty. Sensitivity labels, conditional access, sharing boundaries, odd edge cases around who can see what. If you get it <em>almost<\/em> right, that&#8217;s worse than not doing it at all, because now you&#8217;ve built something that looks polished and quietly leaks data.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What Work IQ is<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Work IQ is the intelligence layer behind Microsoft 365 Copilot, exposed as a developer API. The important distinction is that it doesn&#8217;t just hand you raw data and leave the reasoning to you. It exposes <em>intelligence<\/em>. You ask a question in natural language, it does the assembling, grounding, and reasoning internally, and it returns a Copilot-quality answer with citations, all inside your tenant&#8217;s existing security and compliance boundary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft introduced it at Build 2026 as one of a family of &#8220;IQ&#8221; services: Work IQ for organizational intelligence, alongside Foundry IQ, Fabric IQ, and Web IQ. Work IQ is the one that understands your <em>work<\/em>: emails, meetings, chats, files, people, and the relationships between them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s organized into four domains, and the names are worth learning because they line up pretty neatly with what agents usually need:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Chat<\/strong>: conversational intelligence. You send a question, you get back a fully reasoned, grounded answer. This is what we&#8217;ll use today, via the A2A protocol (and REST, when you&#8217;re calling from a web app).<\/li>\n\n\n\n<li><strong>Context<\/strong>: grounded context, assembled for you. Instead of you running a retrieval pipeline, Work IQ assembles and grounds the relevant organizational context internally and hands the agent ready-to-use input.<\/li>\n\n\n\n<li><strong>Tools<\/strong>: a compact set of generic actions an agent can take across Microsoft 365 (mail, calendar, files, people, chat, sites). More on these in Part 3.<\/li>\n\n\n\n<li><strong>Workspaces<\/strong>: persistent working storage (backed by SharePoint Embedded) where a long-running agent can stash intermediate state inside your tenant boundary. We&#8217;ll get to this in Part 4.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How it&#8217;s different from what you&#8217;re probably doing today<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve used Microsoft Graph, the obvious question is: isn&#8217;t this just Graph with a nicer wrapper? It isn&#8217;t, and that difference is the whole point.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With <strong>Graph<\/strong>, you get <em>data<\/em>. You call <strong>\/me\/messages<\/strong>, you get messages back, and all the reasoning about what matters, how it connects, and what the answer should be is on you. With <strong>Work IQ<\/strong>, you get <em>answers<\/em>. The reasoning happens server-side, with the same grounding quality you see in Copilot.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve built <strong>your own RAG<\/strong> over Microsoft 365 content, Work IQ removes the four hardest parts: you don&#8217;t manage a vector store, you don&#8217;t run sync jobs, you don&#8217;t re-implement permission trimming, and you don&#8217;t own retrieval ranking. Responses are permission-trimmed by design. Every request runs in the context of the signed-in user, and because the API exposes intelligence rather than raw data, an app <em>can&#8217;t<\/em> accidentally sidestep tenant security. That&#8217;s the part I think matters most.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you used the older <strong>Copilot Chat API<\/strong> during preview, Work IQ is the production-ready version of that direction. Same general idea, but now with enterprise SLAs and stable contracts. If you&#8217;re starting something new, this is the one to build on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Choosing a protocol<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Work IQ fits into a few different architectures. The same intelligence runtime is exposed through several protocols, so the grounding and response quality stay consistent whichever one you choose:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table class=\"has-fixed-layout\"><thead><tr><th>Protocol<\/th><th>Use it when\u2026<\/th><th>The caller is\u2026<\/th><\/tr><\/thead><tbody><tr><td><strong>A2A<\/strong> (Agent-to-Agent)<\/td><td>Another agent needs to delegate a task to Work IQ and get a result back<\/td><td>Another agent<\/td><\/tr><tr><td><strong>REST<\/strong><\/td><td>You&#8217;re building an app or service that calls Work IQ programmatically<\/td><td>Your app or backend<\/td><\/tr><tr><td><strong>MCP<\/strong> (local + remote)<\/td><td>An LLM-based client (Copilot, an IDE assistant, a custom agent) invokes Work IQ as a tool<\/td><td>An LLM client<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">For this series I&#8217;m starting with <strong>A2A<\/strong>, because it&#8217;s the most agent-native of the three and it makes the model easy to see. Your code sends a message, Work IQ responds as a peer with a grounded answer. We&#8217;ll cover MCP in Part 3 and REST in Part 4.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>A note on licensing (this changed at GA)<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This part tripped me up, so it&#8217;s worth calling out. During the public preview, Work IQ access leaned on a Microsoft 365 Copilot add-on license, and the sample errors are not especially helpful if that license isn&#8217;t there yet or hasn&#8217;t fully propagated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At GA (June 16), that changes: <strong>Work IQ API access is independent of Copilot licensing and billed consumptively through Copilot Credits.<\/strong> Licensed Copilot users get it across their Copilot experiences and are billed consumptively for custom and third-party agents; unlicensed users are billed consumptively too. There isn&#8217;t a separate Work IQ SKU or a per-user license, and IT can manage the spend from the Microsoft 365 admin center. In practical terms, if you&#8217;re testing against a preview tenant right now, keep the Copilot license assigned and give it 15\u201330 minutes after assignment before expecting solid answers. The index needs a little time to warm up.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>One gotcha before we write code<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you go straight to the <a href=\"https:\/\/github.com\/microsoft\/work-iq-samples\">official samples repo<\/a>, you&#8217;ll see the current samples target the <strong>Work IQ Gateway<\/strong> (workiq.svc.cloud.microsoft) as the dedicated entry point for Work IQ. The <strong>dotnet\/a2a<\/strong> sample follows that path directly, using the Work IQ audience and delegated <strong>WorkIQAgent.Ask<\/strong> scope rather than Microsoft Graph.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s the path I&#8217;ll use throughout this series. If you run into older docs that still reference Graph endpoints, treat the gateway and the sample code as the more current source of truth.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Let&#8217;s make a call<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ll build the smallest possible thing that proves the point: a console app that sends one question to Work IQ over A2A and prints the grounded answer with citations. I&#8217;m deliberately using <strong>raw <code>HttpClient<\/code> + JSON<\/strong> here instead of the A2A SDK, because for a first pass it&#8217;s useful to see exactly what goes over the wire. We&#8217;ll switch to the SDK in Part 2.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Register an Entra app<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before you register your app, there&#8217;s one tenant-level prerequisite that is easy to miss: an organization admin has to enable the Work IQ API in the tenant by creating its service principal. That&#8217;s a one-time setup per organization, not something every developer repeats.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If it hasn&#8217;t been done yet, an admin can run:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>az ad sp create --id fdcc1f02-fc51-4226-8753-f668596af7f7<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">az<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">ad<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">sp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">create<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">--id<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">fdcc1f02-fc51-4226-8753-f668596af7f7<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Once that service principal exists in the tenant, you can register your own client app.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the <a href=\"https:\/\/portal.azure.com\">Azure portal<\/a> \u2192 <strong>Microsoft Entra ID<\/strong> \u2192 <strong>App registrations<\/strong> \u2192 <strong>New registration<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Supported account types:<\/strong> match your tenant (single-tenant is fine for a demo).<\/li>\n\n\n\n<li><strong>Redirect URI:<\/strong> add a <strong>Public client\/native<\/strong> redirect of <a href=\"http:\/\/localhost\">http:\/\/localhost<\/a> so the interactive sign-in can complete.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Then under <strong>API permissions<\/strong>, add the Work IQ delegated permission and grant admin consent. The named delegated scope is <strong>WorkIQAgent.Ask<\/strong> on the Work IQ resource (<strong>api:\/\/workiq.svc.cloud.microsoft<\/strong>). In OAuth terms, that permission is exposed as api:\/\/workiq.svc.cloud.microsoft\/WorkIQAgent.Ask. The samples often request <strong>api:\/\/workiq.svc.cloud.microsoft\/.default<\/strong>, which simply asks for whatever has already been consented on that resource.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"832\" height=\"886\" src=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2026\/06\/image.png\" alt=\"\" class=\"wp-image-635\" style=\"width:608px;height:auto\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2026\/06\/image.png 832w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2026\/06\/image-282x300.png 282w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2026\/06\/image-768x818.png 768w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2026\/06\/image-769x819.png 769w\" sizes=\"auto, (max-width: 832px) 100vw, 832px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Work IQ uses <strong>Entra delegated authentication<\/strong> \u2014 every call runs as the signed-in user, on-behalf-of flows are supported, and application-only auth is deliberately <em>not<\/em> supported. That&#8217;s not a limitation, it&#8217;s the security model: there&#8217;s no &#8220;service account that sees everything,&#8221; because there&#8217;s no scenario where Work IQ returns content outside a specific user&#8217;s permissions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Grab your <strong>app (client) ID<\/strong> and <strong>tenant ID<\/strong> \u2014 we&#8217;ll need both.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: The project<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now let&#8217;s keep the project itself as small as possible: a plain console app and the one package we need for interactive sign-in.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">PowerShell<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>dotnet new console -n WorkIQHello\ncd WorkIQHello\ndotnet add package Microsoft.Identity.Client<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">dotnet new console -n WorkIQHello<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">cd WorkIQHello<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">dotnet add package Microsoft.Identity.Client<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">We only need MSAL to acquire a token interactively. Everything else is just HttpClient and System.Text.Json. This targets .NET 10.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Get a token, send a message<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">With that in place, we can write the whole flow end to end: sign the user in, call the Work IQ gateway, and print the answer that comes back.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>using System.Net.Http.Headers;\nusing System.Text;\nusing System.Text.Json;\nusing Microsoft.Identity.Client;\n\n\/\/ --- 1. Acquire a delegated token for the Work IQ resource ---\nconst string ClientId = \"&lt;your-app-client-id>\";\nconst string TenantId = \"&lt;your-tenant-id>\";\nconst string Scope    = \"api:\/\/workiq.svc.cloud.microsoft\/.default\";\nconst string Endpoint = \"https:\/\/workiq.svc.cloud.microsoft\/a2a\/\";\n\nvar app = PublicClientApplicationBuilder\n    .Create(ClientId)\n    .WithAuthority($\"https:\/\/login.microsoftonline.com\/{TenantId}\")\n    .WithDefaultRedirectUri()\n    .Build();\n\nvar auth = await app\n    .AcquireTokenInteractive(new[] { Scope })\n    .ExecuteAsync();\n\n\/\/ --- 2. Build an HttpClient pointed at the Work IQ gateway ---\nvar http = new HttpClient();\nhttp.DefaultRequestHeaders.Authorization =\n    new AuthenticationHeaderValue(\"Bearer\", auth.AccessToken);\nhttp.DefaultRequestHeaders.Accept.Add(\n    new MediaTypeWithQualityHeaderValue(\"application\/json\"));\n\n\/\/ Opt in to the A2A v1.0 wire format. Without this header the gateway\n\/\/ defaults to v0.3 and the v1.0 method name below returns\n\/\/ JSON-RPC -32601 \"Method not found\". This one line costs people hours.\nhttp.DefaultRequestHeaders.TryAddWithoutValidation(\"A2A-Version\", \"1.0\");\n\n\/\/ --- 3. Build an A2A message wrapped in a JSON-RPC envelope ---\nvar message = new Dictionary&lt;string, object?>\n{\n    &#91;\"role\"&#93;      = \"ROLE_USER\",\n    &#91;\"messageId\"&#93; = Guid.NewGuid().ToString(),\n    &#91;\"parts\"&#93;     = new object[] { new { text = \"What meetings do I have today?\" } },\n    \/\/ Location lets Work IQ resolve \"today\" \/ \"this week\" in the user's local time.\n    &#91;\"metadata\"&#93;  = new Dictionary&lt;string, object>\n    {\n        &#91;\"Location\"&#93; = new\n        {\n            timeZoneOffset = (int)TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes,\n            timeZone = TimeZoneInfo.Local.Id\n        }\n    }\n};\n\nvar rpc = new\n{\n    jsonrpc = \"2.0\",\n    id = Guid.NewGuid().ToString(),\n    method = \"SendMessage\",          \/\/ sync; \"SendStreamingMessage\" for SSE (Part 2)\n    @params = new { message }\n};\n\nvar content = new StringContent(\n    JsonSerializer.Serialize(rpc), Encoding.UTF8, \"application\/json\");\n\n\/\/ --- 4. POST to the gateway base URL \u2014 the method lives in the body, not the path ---\nvar response = await http.PostAsync(Endpoint, content);\nvar body = await response.Content.ReadAsStringAsync();\n\nif (!response.IsSuccessStatusCode)\n{\n    Console.WriteLine($\"{(int)response.StatusCode} {response.StatusCode}\\n{body}\");\n    return;\n}\n\n\/\/ --- 5. Pull the answer out of result.task.artifacts[].parts[].text ---\nusing var doc = JsonDocument.Parse(body);\nvar result = doc.RootElement.GetProperty(\"result\");\n\nConsole.WriteLine(ExtractAnswer(result));\nPrintCitations(result);\n\nstatic string ExtractAnswer(JsonElement result)\n{\n    \/\/ A completed task carries the answer as one or more artifacts.\n    if (result.TryGetProperty(\"task\", out var task) &amp;&amp;\n        task.TryGetProperty(\"artifacts\", out var artifacts))\n    {\n        var sb = new StringBuilder();\n        foreach (var artifact in artifacts.EnumerateArray())\n            if (artifact.TryGetProperty(\"parts\", out var parts))\n                foreach (var p in parts.EnumerateArray())\n                    if (p.TryGetProperty(\"text\", out var t))\n                        sb.Append(t.GetString());\n        return sb.ToString();\n    }\n    return \"(no answer found)\";\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Net<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Http<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Headers<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Text<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">System<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Text<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Json<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Microsoft<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Identity<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #4EC9B0\">Client<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ --- 1. Acquire a delegated token for the Work IQ resource ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">ClientId<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;&lt;your-app-client-id&gt;&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">TenantId<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;&lt;your-tenant-id&gt;&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Scope<\/span><span style=\"color: #D4D4D4\">    = <\/span><span style=\"color: #CE9178\">&quot;api:\/\/workiq.svc.cloud.microsoft\/.default&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">const<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">Endpoint<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;https:\/\/workiq.svc.cloud.microsoft\/a2a\/&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">app<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">PublicClientApplicationBuilder<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">Create<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">ClientId<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">WithAuthority<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">$&quot;https:\/\/login.microsoftonline.com\/{<\/span><span style=\"color: #9CDCFE\">TenantId<\/span><span style=\"color: #CE9178\">}&quot;<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">WithDefaultRedirectUri<\/span><span style=\"color: #D4D4D4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">Build<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">auth<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">await<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">app<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">AcquireTokenInteractive<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\">[] { <\/span><span style=\"color: #9CDCFE\">Scope<\/span><span style=\"color: #D4D4D4\"> })<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    .<\/span><span style=\"color: #DCDCAA\">ExecuteAsync<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ --- 2. Build an HttpClient pointed at the Work IQ gateway ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">http<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">HttpClient<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">http<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">DefaultRequestHeaders<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Authorization<\/span><span style=\"color: #D4D4D4\"> =<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">AuthenticationHeaderValue<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;Bearer&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">auth<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">AccessToken<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">http<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">DefaultRequestHeaders<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Accept<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Add<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">MediaTypeWithQualityHeaderValue<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;application\/json&quot;<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ Opt in to the A2A v1.0 wire format. Without this header the gateway<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ defaults to v0.3 and the v1.0 method name below returns<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ JSON-RPC -32601 &quot;Method not found&quot;. This one line costs people hours.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">http<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">DefaultRequestHeaders<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryAddWithoutValidation<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;A2A-Version&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;1.0&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ --- 3. Build an A2A message wrapped in a JSON-RPC envelope ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">message<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Dictionary<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">object<\/span><span style=\"color: #D4D4D4\">?&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #CE9178\">&quot;role&quot;<\/span><span style=\"color: #D4D4D4\">&#93;      = <\/span><span style=\"color: #CE9178\">&quot;ROLE_USER&quot;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #CE9178\">&quot;messageId&quot;<\/span><span style=\"color: #D4D4D4\">&#93; = <\/span><span style=\"color: #9CDCFE\">Guid<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">NewGuid<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">ToString<\/span><span style=\"color: #D4D4D4\">(),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #CE9178\">&quot;parts&quot;<\/span><span style=\"color: #D4D4D4\">&#93;     = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">object<\/span><span style=\"color: #D4D4D4\">[] { <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #9CDCFE\">text<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;What meetings do I have today?&quot;<\/span><span style=\"color: #D4D4D4\"> } },<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Location lets Work IQ resolve &quot;today&quot; \/ &quot;this week&quot; in the user&#39;s local time.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    &#91;<\/span><span style=\"color: #CE9178\">&quot;metadata&quot;<\/span><span style=\"color: #D4D4D4\">&#93;  = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">Dictionary<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">object<\/span><span style=\"color: #D4D4D4\">&gt;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        &#91;<\/span><span style=\"color: #CE9178\">&quot;Location&quot;<\/span><span style=\"color: #D4D4D4\">&#93; = <\/span><span style=\"color: #569CD6\">new<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">timeZoneOffset<\/span><span style=\"color: #D4D4D4\"> = (<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #D4D4D4\">)<\/span><span style=\"color: #9CDCFE\">TimeZoneInfo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Local<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">BaseUtcOffset<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">TotalMinutes<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #9CDCFE\">timeZone<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">TimeZoneInfo<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Local<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Id<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">};<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">rpc<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">jsonrpc<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;2.0&quot;<\/span><span style=\"color: #D4D4D4\">,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">id<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">Guid<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">NewGuid<\/span><span style=\"color: #D4D4D4\">().<\/span><span style=\"color: #DCDCAA\">ToString<\/span><span style=\"color: #D4D4D4\">(),<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">method<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;SendMessage&quot;<\/span><span style=\"color: #D4D4D4\">,          <\/span><span style=\"color: #6A9955\">\/\/ sync; &quot;SendStreamingMessage&quot; for SSE (Part 2)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">@params<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> { <\/span><span style=\"color: #9CDCFE\">message<\/span><span style=\"color: #D4D4D4\"> }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">};<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">content<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">StringContent<\/span><span style=\"color: #D4D4D4\">(<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">JsonSerializer<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Serialize<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">rpc<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #9CDCFE\">Encoding<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">UTF8<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&quot;application\/json&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ --- 4. POST to the gateway base URL \u2014 the method lives in the body, not the path ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">response<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">await<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">http<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">PostAsync<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">Endpoint<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">content<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">body<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">await<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">response<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Content<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">ReadAsStringAsync<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (!<\/span><span style=\"color: #9CDCFE\">response<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">IsSuccessStatusCode<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Console<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">WriteLine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">$&quot;{(<\/span><span style=\"color: #569CD6\">int<\/span><span style=\"color: #CE9178\">)<\/span><span style=\"color: #9CDCFE\">response<\/span><span style=\"color: #CE9178\">.<\/span><span style=\"color: #9CDCFE\">StatusCode<\/span><span style=\"color: #CE9178\">} {<\/span><span style=\"color: #9CDCFE\">response<\/span><span style=\"color: #CE9178\">.<\/span><span style=\"color: #9CDCFE\">StatusCode<\/span><span style=\"color: #CE9178\">}<\/span><span style=\"color: #D7BA7D\">\\n<\/span><span style=\"color: #CE9178\">{<\/span><span style=\"color: #9CDCFE\">body<\/span><span style=\"color: #CE9178\">}&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">\/\/ --- 5. Pull the answer out of result.task.artifacts[].parts[].text ---<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C586C0\">using<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">JsonDocument<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Parse<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">body<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">doc<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">RootElement<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;result&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">Console<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">WriteLine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #DCDCAA\">ExtractAnswer<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">));<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">PrintCitations<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">string<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">ExtractAnswer<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">JsonElement<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ A completed task carries the answer as one or more artifacts.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;task&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">task<\/span><span style=\"color: #D4D4D4\">) &amp;&amp;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">task<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;artifacts&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">artifacts<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sb<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #569CD6\">new<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4EC9B0\">StringBuilder<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">artifact<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">artifacts<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">EnumerateArray<\/span><span style=\"color: #D4D4D4\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">artifact<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;parts&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">parts<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">parts<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">EnumerateArray<\/span><span style=\"color: #D4D4D4\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">p<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;text&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">                        <\/span><span style=\"color: #9CDCFE\">sb<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">Append<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">t<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetString<\/span><span style=\"color: #D4D4D4\">());<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">sb<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">ToString<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;(no answer found)&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">A few details are worth calling out because they&#8217;re exactly the kind of thing that wastes an hour if you miss them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>You POST to the base URL.<\/strong> Unlike a REST API where the verb is the path, A2A puts the method name (SendMessage) <em>inside<\/em> the JSON-RPC body. The gateway endpoint is the same for every call.<\/li>\n\n\n\n<li><strong>role <\/strong>is ROLE_USER, in screaming snake case, and there&#8217;s no kind discriminator on parts. That&#8217;s the A2A v1.0 shape \u2014 and the reason the A2A-Version: 1.0 header matters.<\/li>\n\n\n\n<li><strong>Location <\/strong>metadata isn&#8217;t optional for time-sensitive questions. Ask &#8220;what&#8217;s on my calendar today&#8221; without it and Work IQ has no idea what &#8220;today&#8221; means for you.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Show the citations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The reason a Work IQ answer is actually useful is that it tells you <em>where the information came from<\/em>. Citations come back in the response metadata under attributions:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">C#<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>static void PrintCitations(JsonElement result)\n{\n    \/\/ Metadata can sit on the task's status message; shape mirrors the streaming case.\n    if (!result.TryGetProperty(\"task\", out var task) ||\n        !task.TryGetProperty(\"status\", out var status) ||\n        !status.TryGetProperty(\"message\", out var msg) ||\n        !msg.TryGetProperty(\"metadata\", out var meta) ||\n        !meta.TryGetProperty(\"attributions\", out var attributions) ||\n        attributions.ValueKind != JsonValueKind.Array)\n        return;\n\n    Console.WriteLine(\"\\nSources:\");\n    foreach (var a in attributions.EnumerateArray())\n    {\n        var name = a.TryGetProperty(\"providerDisplayName\", out var n) ? n.GetString() : \"(source)\";\n        var url  = a.TryGetProperty(\"seeMoreWebUrl\", out var u) ? u.GetString() : \"\";\n        Console.WriteLine($\"  \u2022 {name}  {url}\");\n    }\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">static<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">void<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">PrintCitations<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #4EC9B0\">JsonElement<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\">    \/\/ Metadata can sit on the task&#39;s status message; shape mirrors the streaming case.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (!<\/span><span style=\"color: #9CDCFE\">result<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;task&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">task<\/span><span style=\"color: #D4D4D4\">) ||<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        !<\/span><span style=\"color: #9CDCFE\">task<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;status&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">status<\/span><span style=\"color: #D4D4D4\">) ||<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        !<\/span><span style=\"color: #9CDCFE\">status<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;message&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">msg<\/span><span style=\"color: #D4D4D4\">) ||<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        !<\/span><span style=\"color: #9CDCFE\">msg<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;metadata&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">meta<\/span><span style=\"color: #D4D4D4\">) ||<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        !<\/span><span style=\"color: #9CDCFE\">meta<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;attributions&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">attributions<\/span><span style=\"color: #D4D4D4\">) ||<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">attributions<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">ValueKind<\/span><span style=\"color: #D4D4D4\"> != <\/span><span style=\"color: #9CDCFE\">JsonValueKind<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">Array<\/span><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #C586C0\">return<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">Console<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">WriteLine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;<\/span><span style=\"color: #D7BA7D\">\\n<\/span><span style=\"color: #CE9178\">Sources:&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #C586C0\">foreach<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">a<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #C586C0\">in<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">attributions<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">EnumerateArray<\/span><span style=\"color: #D4D4D4\">())<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">a<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;providerDisplayName&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">) ? <\/span><span style=\"color: #9CDCFE\">n<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetString<\/span><span style=\"color: #D4D4D4\">() : <\/span><span style=\"color: #CE9178\">&quot;(source)&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">url<\/span><span style=\"color: #D4D4D4\">  = <\/span><span style=\"color: #9CDCFE\">a<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">TryGetProperty<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;seeMoreWebUrl&quot;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #569CD6\">out<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\">) ? <\/span><span style=\"color: #9CDCFE\">u<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">GetString<\/span><span style=\"color: #D4D4D4\">() : <\/span><span style=\"color: #CE9178\">&quot;&quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">Console<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">WriteLine<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">$&quot;  \u2022 {<\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #CE9178\">}  {<\/span><span style=\"color: #9CDCFE\">url<\/span><span style=\"color: #CE9178\">}&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Run it (<strong>dotnet run<\/strong>), sign in when the browser pops up, and you should get back something like:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>Today you have: 9 AM standup, 11 AM review with Dana, 2 PM customer call.\n\nSources:\n  \u2022 Calendar  https:\/\/outlook.office.com\/...<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">Today<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">you<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">have:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">9<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">AM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">standup,<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">11<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">AM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">review<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">with<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Dana,<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">PM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">customer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">call.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Sources:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #DCDCAA\">\u2022<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Calendar<\/span><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #CE9178\">https:\/\/outlook.office.com\/...<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s a grounded, permission-trimmed answer over your real Microsoft 365 data, and it took roughly forty lines of code to get there. No connectors, no index, no permission logic. The user signs in, and they only see what they&#8217;re already allowed to see.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Where this is going<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">What we built today is intentionally bare-bones: one synchronous question, raw JSON, no SDK. It proves the model, but it&#8217;s not how you&#8217;d ship a real agent.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <strong>Part 2<\/strong> we&#8217;ll rebuild this properly with the A2A .NET SDK: multi-turn conversations using <code>contextId<\/code> so the agent remembers the thread, streaming responses over SSE, and cleaner citation handling. Then <strong>Part 3<\/strong> moves into the Work IQ MCP and its ten generic tools, and <strong>Part 4<\/strong> gets into Workspaces for long-running agents.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve followed my SharePoint and Foundry memory posts, that&#8217;s really the through-line here. We&#8217;ve gone from grounding an agent in <em>one<\/em> source that I had to wire up myself to an intelligence layer that can ground across <em>all<\/em> of Microsoft 365 and enforce permissions for me. That&#8217;s a real shift in where the hard work lives, and it&#8217;s a much better place to be building from.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Code for this series will be on my GitHub at <\/em><a href=\"https:\/\/github.com\/AhmadiRamin\/work-iq-samples\">work-iq-samples<\/a><em>. <\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Next up: building the agent with the A2A SDK.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;ve built an enterprise agent that needs to understand what&#8217;s actually happening inside an organization \u2014 who&#8217;s working on what, what was decided in last week&#8217;s meeting, which document is the latest version of the proposal \u2014 you already know the hard part isn&#8217;t the model. It&#8217;s the context. I&#8217;ve spent a good chunk of the last year on exactly this problem. In my SharePoint agents series I grounded an agent in SharePoint content,&hellip;<\/p>\n","protected":false},"author":1,"featured_media":643,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55,72,65,5,6],"tags":[49,9,76],"class_list":["post-624","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-ai-agent","category-azure-ai-foundry","category-microsoft-azure","category-microsoft-graph","tag-ai","tag-azure","tag-workiq"],"_links":{"self":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=624"}],"version-history":[{"count":15,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/624\/revisions"}],"predecessor-version":[{"id":642,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/624\/revisions\/642"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/media\/643"}],"wp:attachment":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}