Lesson 7 of Harness Engineering in Go — a sensitive action pauses for a human decision, and the whole suspension is nothing more than a Lesson 2 checkpoint marked awaiting_approval.
Series finale, Lesson 7: a sensitive action pauses for human approval, where suspension is just a Lesson 2 checkpoint marked awaiting_approval, the deadline is checked first so a late yes is void, and the action must be idempotent.
Lesson 6 of Harness Engineering in Go — a supervisor splits a task, fans out to concurrent workers behind a semaphore, and fans the results back in decomposition order, with each worker's failure (or panic) isolated to one result.
Lesson 6: bounded fan-out behind a semaphore, ordered fan-in via a pre-sized results slice, and per-worker fault isolation so one sub-agent panicking becomes one failed result instead of crashing the whole run.
Lesson 5 of Harness Engineering in Go — a triage step that first-matches a keyword and hands the request to a specialist, and the exact place a substring table stops being able to think.
Lesson 5: a triage router first-matches a keyword to hand intent to a specialist, and the exact point a substring table stops being able to think.
Lesson 4 of Harness Engineering in Go — three collaborating stores (a thread, a knowledge index, and a summarizer) behind interfaces, and an honest accounting of where each local stand-in leaks.
Lesson 4: memory is three stores, not one — an append-only thread, a keyword knowledge index, and a lossy first-and-last summarizer — and an honest account of where each local stand-in leaks against Azure.
Lesson 3 of Harness Engineering in Go — how a context deadline and `exec.CommandContext` reap a runaway snippet, why the two-shaped `Result` distinguishes a timeout from a failure, and the leak that makes a local subprocess a teaching tool, not a security boundary.
Lesson 3: run agent-written code behind a hard timeout with exec.CommandContext, distinguish OK from TimedOut, and face the leak — a subprocess is not a security boundary.
How ADK's config loader turns a declarative YAML file into a fully-built agent — and why treating an agent as data changes who gets to edit it.
Defining an agent declaratively in YAML and loading it via from_config — the loader reads, resolves, and validates the config into a built agent, so config-as-data works without writing code.
Lesson 2 of Harness Engineering in Go — a workflow that saves its progress after each step and picks up exactly where it died, proven by a test that kills a real subprocess mid-run.
Lesson 2: a workflow that checkpoints after every step and resumes from the last one after a crash, why at-least-once execution forces idempotent steps, and the atomic-rename store that survives a killed process.
How caching a large, stable prompt prefix cuts latency and cost — and the ADK config that decides when it pays off.
Context caching cuts latency and cost by caching large, stable context — system prompt, reference docs, tool definitions — so repeated calls don't re-send and re-process the same tokens.
Lesson 1 of Harness Engineering in Go — why the input guardrail is a hard block, not a warning, and how a plain `net/http` handler wraps the model call so it tests without a running server.
Lesson 1: why the input guardrail is a hard block rather than flag-and-pass, why it counts runes instead of bytes, and how a plain net/http handler wraps the (stubbed) model call so it tests with httptest.
Post 23 of 26 in "Google ADK, Concept by Concept" — how a planner turns one-shot answers into inspectable plan-then-act reasoning.
Structuring an agent's reasoning: planners that make the model plan-then-act (ReAct-style), the built-in thinking feature, and how a planner improves multi-step tool use over naive prompting.
The final lesson: a recipe agent whose JSON replies are turned into trackable state snapshots by a middleware, so the client can render the recipe as it evolves.
The server side of AG-UI state management: middleware emits a DataContent state snapshot from the model's JSON so the client can adopt shared state across turns.
Seven patterns that turn a bare model call into production agent infrastructure — each written first as offline Go behind an interface, so the leap to Azure is a swap, not a rewrite.
Seven patterns that turn a bare model call into production agent infrastructure, each written first as offline Go behind an interface (the seam) so the leap to Azure is a swap, not a rewrite.
How ADK closes the write-code, run-it, read-the-output loop — and why "unsafe" is a warning, not a typo.
Letting an agent write and run code: built-in and container-based code executors, safe sandboxed execution, how results flow back into the conversation, and the security tradeoffs.
The server hosts an agent with one approval-gated tool — the model may propose calling it, but the framework refuses to run it until a human on the other end says yes.
The server side of AG-UI human-in-the-loop: gate a tool with tool.ApprovalRequiredFunc so the server suspends the run and resumes on the client's decision.
How ADK skills bundle instructions, tools, and resources into folders an agent can browse and load on demand.
Skills package reusable capabilities — instructions, tools, resources, including file-based skills — so they can be discovered and attached to agents, promoting reuse across projects.
The mirror image of backend tools: the server hosts the agent but the tools live on the client, so the handler must forward tool calls instead of running them.
The server side of AG-UI frontend tools: set DisableFuncAutoCall so the server forwards tool calls to the client to execute and awaits the result.
Wrapping Go agents in A2A, MCP, and AG-UI transports, then a full client/server app that ties the whole series together.
Wrap Go agents in A2A, MCP, and AG-UI transports, then run the end-to-end client/server capstone where a host agent uses remote specialists as tools.
cross-cutting concerns registered once on the Runner instead of copied onto every agent
Plugins are cross-cutting hooks that apply globally across every agent, tool, and runner — logging, policy, metrics, caching — as opposed to per-agent callbacks. When a plugin beats a callback.
Same AG-UI transport as the getting-started server, but now the hosted agent carries a tool the model can call server-side while it answers.
The server side of AG-UI backend tools: attach server-owned function tools to the Foundry agent so the tool round-trip stays entirely server-side.
Durable workflows in Go: checkpoint and rehydrate, pause on a RequestPort for a human, nest sub-workflows, and coordinate through scoped shared state.
Durable MAF workflows in Go: checkpoint and rehydrate a fresh graph, pause on a RequestPort for a human, nest sub-workflows, and coordinate via scoped shared state.
How ADK's model abstraction lets you swap Gemini for Claude, GPT, or Ollama without touching a line of agent code
ADK is model-agnostic: use Gemini natively or plug in Claude, GPT, or Ollama via LiteLLM and a model registry, swapping the model without changing agent code.
The client half streams events over SSE; this is the process on the other end of the wire — a Foundry agent wrapped in an HTTP handler that speaks AG-UI.
The AG-UI server half: wrap a Foundry agent in aguiprovider.NewJSONHTTPHandler and serve it over HTTP/SSE for any AG-UI client to drive.
The prebuilt orchestration builders in agent-framework-go — Sequential, Concurrent, Group Chat — plus wrapping a whole workflow as one agent.
The Sequential, Concurrent, and Group Chat orchestration builders in agent-framework-go, plus wrapping a whole workflow as one nestable agent.
Post 18 of 26 in "Google ADK, Concept by Concept" — retrieval tools, grounding metadata, rendering citations, and the retrieve→augment→generate loop.
Grounding answers in real data: retrieval tools, grounding metadata returned with responses, rendering citations from that metadata, and the retrieve-augment-generate RAG pattern in ADK.
The final lesson ties the whole Go tutorial into one small product: an assistant that answers questions about your docs — grounded, cited, and refusing to guess.
The capstone: a grounded DocQA agent that answers only from embedded docs via a search_docs tool, cites sources, and refuses to guess — with an optional reviewer.
Agents as graph executors in Go: switch routing, fan-out/fan-in barriers, and mixing typed function nodes with agent nodes.
Agents as Go workflow executors: switch routing, fan-out and fan-in barriers, and mixing typed function nodes with agent nodes in one graph.
Two open protocols that let an agent reach outside its own process — one to borrow tools, one to call other agents as peers.
Two interoperability protocols: MCP lets an agent consume tools from external servers, and A2A — HTTP for agents — lets one agent discover and call another remote agent as a peer over HTTP.
This lesson hosts one specialized Foundry agent over the A2A protocol, publishing an agent card the client can discover.
Host one Foundry agent over A2A: newMux pins the card interface URL, wraps the agent in an a2aprovider executor, and serves the card plus JSON-RPC routes.
The graph model underneath every multi-agent app: executors as nodes, edges as data flow, and typed events streaming out of `WatchStream` as it runs.
The MAF workflow model in Go: executors bound to IDs, AddEdge wiring, WithOutputFrom, and typed WatchStream events - plus an upstream route-builder fix.
Stack the guardrails — callbacks, model filters, restricted tools, and clean-room sandboxing — so that if one layer misses, the next one catches
Layered defense-in-depth for agents: input/output guardrails via callbacks, Gemini safety settings, restricting tools, and sandboxing untrusted actions.
This lesson builds a Foundry host agent that discovers remote A2A agents by their cards and calls each one as a tool.
A Foundry host agent resolves remote A2A agent cards and turns each remote agent into a callable tool with agenttool.New over the a2aprovider.
Wrap every run in an OpenTelemetry span, gate risky tool actions behind a permission handler, and swap model providers behind one agent.Agent.
Wrap every MAF run in an OpenTelemetry span, gate risky tool actions behind a permission handler, and swap Anthropic, OpenAI, Gemini, Copilot, and Azure behind one agent.
How OpenTelemetry traces, structured logs, and token metrics turn an agent's event stream into something you can debug in production.
Seeing inside a running agent: OpenTelemetry tracing with spans for agent, model, and tool steps, structured logging, and exporting traces to debug latency and tool-call trajectories.
How a whole workflow binds as a single executor inside a larger workflow, so pipelines compose two levels deep.
inproc.BindSubworkflowAsExecutor binds a whole workflow as one node; an order pipeline nests Payment and FraudCheck two levels deep, and inner events still bubble up.
A guardrail that blocks a run before the model, chained ahead of a logger — and the upstream nil-update panic I fixed along the way.
A guardrail middleware that blocks an MAF Go run before the model, chained ahead of a logger — plus the tool-approval nil-update panic I fixed upstream in PR #472.
How `adk deploy` builds, pushes, and ships an agent in a single step — and the ack-after-invocation rule that keeps event-driven agents reliable.
Deploying an agent: adk deploy with its cloud_run and agent_engine subcommands, containerizing the app, and reliability rules like ack-after-invocation so failures are redelivered, not dropped.
How one executor stores a value in scoped shared state and later executors read it back — instead of copying a whole payload down every edge.
One executor stores a document with QueueStateUpdate; fan-out counters read it back with ReadState, and an AddFanInBarrierEdge aggregates once both deliver. Offline.
Decoding typed structs from a run, draining a streamed response, and sending an image with `RunMessage`.
Decode typed structs from a run, drain a streamed response by ranging it, and send an image with RunMessage and DataContent.
How ADK turns "did the agent behave correctly?" into a number you can gate a merge on.
Measuring agent quality: eval sets, scoring both the trajectory (right tools, right order) and the final response, criteria configs, and the adk eval CLI — a Python-first workflow today.
How WithTelemetry instruments a whole workflow with OpenTelemetry spans, then agentworkflow.NewAgent wraps the graph so it behaves like one agent.
WithTelemetry instruments a French-to-English workflow with OpenTelemetry spans, then agentworkflow.NewAgent wraps the graph so RunText drives the whole pipeline.
A Session threads history into each run; a ContextProvider carries memory across sessions — and because a Session is JSON, both survive a process restart.
A Session threads history into each run and a ContextProvider carries memory across sessions. Because a Session is JSON, both survive a process restart.
token streaming, the accumulate-and-reconcile consumer pattern, and full-duplex live streaming for voice
Consuming output as it is produced: partial events and token streaming, the accumulate-and-reconcile consumer pattern, and bidi/live streaming for voice and interactive UIs.
How a workflow graph forms a cycle: two executors feed each other until one yields an output — the workflow analogue of a while-loop.
A workflow graph is not a DAG: two edges form a GuessNumber to Judge cycle that runs a binary search and exits only when Judge yields an output. The while-loop analogue.
Wrap a typed Go function as a tool, let the model call it, and compose whole agents as tools.
Wrap a typed Go function as a tool with functool.MustNew, let the model call it, and compose whole agents as tools with agenttool.New.
How an agent actually runs — a Runner drives an invocation and hands you back a stream of events, not a single answer.
How ADK runs an agent: the Runner drives an invocation that yields a stream of Event objects — content, tool calls, state deltas, control signals. The event loop explains streaming, callbacks, and state.
How a RequestPort pauses a workflow, emits a request to a human, and feeds their answer back into the graph.
A RequestPort emits a RequestInfoEvent and suspends the workflow; the driver answers with SendResponse. A guess-the-number cycle shows the pause/resume mechanism.
The minimal loop in Go: a Foundry provider, an Agent with instructions, run collected and streamed — and what RunText hands back.
The minimal MAF loop in Go: a foundryprovider agent, DefaultAzureCredential, and one RunText you either Collect or range over as a Go 1.23 iterator.
before/after the agent, model, and tool steps — and the single short-circuit rule that turns them into guardrails
Callbacks are lifecycle hooks around the agent, model, and tool steps — before/after each — used for guardrails (short-circuit by returning a response), logging, and mutating requests and responses.
How an edge assigner delivers one message to a chosen subset of targets — a multi-way switch that may fall through to more than one case.
WithEdgeAssigner yields target indexes via an iter.Seq[int], so a single message reaches several branches at once — a long email goes to both assistant and summary, offline.
Why I learned the whole framework in Go by writing one runnable lesson per concept, against Azure AI Foundry, instead of reading the docs top to bottom.
I learned the whole Microsoft Agent Framework in Go by building one runnable lesson per concept against Azure AI Foundry. Here is the 12-track map.
ReadonlyContext, CallbackContext, ToolContext, InvocationContext — and why the read-only vs mutable distinction is a feature, not a limitation.
The context objects ADK passes into tools and callbacks — InvocationContext, ToolContext, CallbackContext, ReadonlyContext — what each exposes and why the read-only vs mutable split matters.
How a switch builder fans one edge into three mutually-exclusive branches — the workflow analogue of switch/case/default.
AddSwitch/AddCase/WithDefault fans one edge into three mutually-exclusive branches with a guaranteed fallback — the workflow analogue of switch/case/default, fully offline.
Session state is for small text and JSON. When your agent produces a PNG, a PDF, or a WAV, it belongs in the artifact store — binary-native, versioned, and out of the session record.
Artifacts are binary/file data agents produce or consume: ArtifactService saves and versions named artifacts, loaded and saved via context, keeping large blobs out of session state.
How a graph workflow forks: a predicate on each edge decides whether a message may pass, turning the graph into an if/else expressed as data flow.
The first 03-workflows lesson: AddDirectEdge attaches a func(any) bool to each edge so a spam-detection graph forks into send vs. handle-spam branches, offline.
State remembers things inside one chat; Memory is the searchable archive that lets an agent recall what you told it weeks ago.
Memory is long-term recall across sessions, distinct from per-session state: MemoryService stores and retrieves prior context, surfaced via a recall tool so an agent remembers a user over time.
How to express the classic MapReduce word-count as a five-stage workflow graph — fan-out to mappers, barrier to a shuffler, fan-out to reducers, barrier to completion.
MapReduce word-count as a five-stage workflow: fan-out to mappers, barrier to a shuffler, fan-out to reducers, barrier to completion, coordinated via shared state.
A `Session` is the conversation; `state` is the key-value bag agents and tools read and write — and the prefix on a key decides how long it lives.
A Session holds a conversation; state is a scoped key-value store (session/user/app/temp) read and written by tools, injected into instructions via {state} templating, and persisted by SessionService.
How to broadcast one input to several executors in parallel and join their answers with a barrier — the core workflow graph primitives, with no LLM in the way.
A start executor broadcasts a question to two experts via a fan-out edge; a fan-in barrier edge joins both answers before the aggregator yields output.
How a plain function becomes a callable tool, how ToolContext reaches session state, and how long-running tools pause a run for a human.
Tools give agents capabilities: a plain function becomes a tool with its signature as the schema, plus ToolContext, built-in tools, and long-running/human-in-the-loop tools across Python and Go.
How to pause a workflow to ask a human, checkpoint every super-step, then rewind the whole graph to a saved checkpoint and replay.
A RequestPort pauses to ask a human for a guess while every super-step is checkpointed, then RestoreCheckpoint rewinds the whole graph including tries state.
How one agent routes work to specialists — and why the description field is the most important string you write.
Agent hierarchies and LLM-driven delegation: sub_agents, how the description field drives auto-transfer, and coordinator/dispatcher patterns — contrasted with deterministic workflow agents.
How to snapshot a workflow after every super-step, then rewind the same live run to an earlier checkpoint and replay from it.
Same guess-the-number graph, but RestoreCheckpoint rewinds the live run to the 6th snapshot and replays forward — no fresh workflow instance needed.
When you want fixed control flow, don't ask the model — wire it yourself.
Sequential, Parallel, and Loop agents compose sub-agents in fixed patterns — deterministic orchestration where you, not the model, decide control flow, with state flowing between steps.
How to snapshot a running workflow at every super-step, then throw the instance away and rebuild a fresh workflow that resumes from a saved checkpoint.
A cyclic guess-the-number workflow snapshots state each super-step, then a brand-new workflow instance is rehydrated from a checkpoint via ResumeStreaming.
description, instruction, generation params, and structured output — the dials on almost every agent you'll build
The four knobs on almost every ADK agent: description (for delegation), instruction with {state} templating, generation params, and structured output — Python Pydantic model vs Go genai.Schema.
How to collapse a whole multi-agent workflow into a single agent so callers use it exactly like any leaf agent.
A concurrent French+English workflow is hosted as one agent via agentworkflow.NewAgent, with IncludeOutputsInResponse surfacing the merged output.
An `LlmAgent`, a `Runner`, a `Session`, and a CLI that runs it all — the four pieces the other 25 concepts sit on top of.
The smallest ADK agent and the machinery around it: an LlmAgent, the Runner, a Session, and the adk CLI (adk web / adk run) that runs your agent with a dev UI or REPL — no server code.
How a multi-agent group chat pauses to ask a human for approval before one gated tool is allowed to run.
A QA and DevOps agent collaborate in a group chat where DeployToProduction is gated by tool.ApprovalRequiredFunc, pausing the workflow for human approval.
How two Foundry agents cooperate inside a cyclic graph workflow where one of them owns the loop control.
Two Foundry agents cooperate in a cyclic workflow: a SloganWriter drafts, a FeedbackProvider critiques and owns loop control via YieldOutput vs SendMessage.
This lesson teaches how to build a cyclic workflow where a Writer and Critic loop until approval, using `AddSwitch` to route on structured output.
A cyclic Writer-Critic-Summary workflow: the Critic emits a structured CriticDecision, AddSwitch routes on Approved, and Context state caps the revision loop at maxIterations.
This lesson teaches how deterministic function executors and agent-backed executors compose in one graph with the same `AddEdge` wiring.
One workflow that mixes deterministic executors with two Foundry agent nodes for jailbreak detection and response, joined by the same AddEdge wiring and TurnToken triggering.
This lesson teaches how to embed a whole built workflow as a single executor inside a larger one — workflows compose.
Embed an entire built workflow as one executor with inproc.BindSubworkflowAsExecutor, composing a Prefix to SubWorkflow to PostProcess parent graph that runs fully offline.
This lesson teaches how to chain three role-specialised agents — researcher → fact_checker → reporter — into one sequential workflow and stream each stage.
A sequential workflow of three role-specialised Foundry agents — researcher, fact_checker, reporter — built with NewSequentialWorkflowBuilder and streamed stage by stage.
This lesson teaches that orchestration is a property of the workflow, not the agents — the same three agents drop into three different built-in graph shapes.
The same three agents dropped into three built-in agentworkflow builders — sequential, concurrent, and round-robin group chat — showing orchestration is a property of the graph, not the agents.
This lesson teaches how to host real `agent.Agent`s as workflow executors and chain them into a sequential pipeline.
Host three translation agents as workflow executors and chain them French to Spanish to English, using DisableForwardIncomingMessages and a TurnToken to drive a strict pipeline.
This lesson teaches how to build a two-executor pipeline and watch it run as a live stream of typed events.
Your first Agent Framework Go workflow: two string executors wired by an edge, run with RunStreaming and watched as a stream of typed events, fully offline.
Compose three kinds of Agent Skill — code-defined, struct-based, and file-based — into a single agent through one skills context provider.
One skills ContextProvider blending three origins: in-memory volume and temperature skills plus a file-based unit-converter, unified behind one tool surface for the model.
An Agent Skill — on-demand instructions, resources, and scripts — defined entirely in Go, with no SKILL.md files on disk.
An Agent Skill built from Go closures: instructions, a static and a runtime-generated resource, and a convert script that runs in-process with no SKILL.md files.
Teach an agent a capability from a folder of files — a SKILL.md manifest, resources, and scripts — loaded on demand via progressive disclosure.
Teach an agent from a SKILL.md manifest, resources, and scripts on disk: fsskills scans the tree and a skills ContextProvider exposes load, read, and run tools.
The provider is the swappable back end: the same Joker agent, one-shot and streaming, now through the OpenAI API.
The same Joker agent, one-shot and streaming, through openaiprovider: openai.NewClient reads OPENAI_API_KEY and the model name lives in AgentConfig, not a Foundry deployment.
A provider whose "credential" is a local process, gated by a human-in-the-loop permission handler for every action the model wants to take.
A provider whose credential is a local copilot CLI process, with an OnPermissionRequest handler that approves or rejects each shell action the model wants to run.
How swapping in the Gemini provider changes the constructor and credential — and nothing else about your agent.
The Joker agent, unchanged, now backed by Google Gemini: geminiprovider.NewAgent takes a genai.Client and an API key instead of an Azure token credential.
This lesson teaches how to connect to a remote MCP server and decorate the tools it exposes with your own local behavior before an agent uses them.
List a remote MCP server's tools, then wrap each FuncTool with a logging decorator via embedding plus one Call override — MCP tools compose like any tool.FuncTool.
This lesson teaches how to attach the hosted web-search tool and read the citation annotations the service returns with its answer.
Attach hostedtool.WebSearch so Foundry grounds its answer on live results, then pull CitationAnnotations off content headers with a pure, unit-testable extractor.
This lesson teaches the hosted tool: a marker that lets the Foundry service run code the model writes, instead of a Go function you implement.
Attach hostedtool.CodeInterpreter, a zero-value marker with no Run method, so Foundry executes model-written Python in a sandbox to solve sin(x) + x^2 = 42.
This lesson teaches how to bundle related function tools onto a Go type and attach the whole group to an agent as one slice.
Bundle GetWeather and GetCurrentTime onto one Go type, expose them as a tool.Tool slice, and let the model call both in a single turn — plugins as an organizing idea.
This lesson teaches a middleware chain where a guardrail can block a run before the model is ever called, chained ahead of a logger.
Chain a guardrail middleware that yields its own refusal and skips the model ahead of a logger — short-circuiting a harmful request offline before Foundry is called.
This lesson teaches the simplest form of multi-agent delegation: wrapping one agent as a tool another agent can call.
Wrap a specialist WeatherAgent with agenttool.New into a tool.Tool and hand it to a French TravelAgent — one model orchestrating another with no workflow engine.
This lesson teaches how to send a question and an image together in one message to a vision-capable Foundry agent.
Put a TextContent and a base64 DataContent JPEG in one message and hand it to a vision agent — multimodal input with no upload step, embedded at compile time.
This lesson teaches how a Foundry agent borrows tools from a remote MCP server and calls them as if they were local functions.
Connect a Foundry agent to Microsoft Learn's public MCP endpoint over streamable HTTP, list its tools, and hand the whole slice to the agent as proxied tools.
otelprovider.NewMiddleware wraps every run in an OpenTelemetry span tagged with gen_ai attributes — the same one-line middleware hook you use for logging.
How to serialize an agent.Session to disk and resume it later, so a follow-up prompt still remembers earlier turns across a process restart.
An agent.Session serializes with encoding/json, so you can marshal it to disk or a database and resume it later with the model still remembering earlier turns.
How to make the model return a typed Go struct instead of prose — hand RunText a pointer, get back populated fields.
Pass RunText a pointer to a Go struct via WithStructuredOutput and the framework asks the model for matching JSON, then unmarshals it straight into your fields.
How to gate a sensitive tool behind human consent: the run pauses, hands you an approval request, and only calls the tool once you approve.
Wrap a tool with ApprovalRequiredFunc and the run pauses with a ToolApprovalRequestContent; approve it, feed the decision back on the same session, and the tool fires.
How to wrap an ordinary Go function as a tool the model can call, with the schema derived automatically from its types.
Wrap a plain Go func with functool.MustNew and the framework derives its JSON schema and drives the tool call inside a single RunText — two model round-trips, one call.
How to keep a conversation's history on the Foundry service instead of in local memory, so the client never resends the transcript.
Create a Foundry project conversation, bind its ID into a session with WithServiceID, and let the service keep the transcript across turns without resending it.
How an agent.Session carries conversation history so a second prompt can refer back to the first.
A client-side agent.Session carries conversation history so a second prompt can refer back to the first. Create it with CreateSession, thread it with WithSession.
How the Foundry provider snaps a project endpoint, a credential, and a model deployment name into a runnable agent.
The Foundry provider is three inputs: a project endpoint, a credential, and a model deployment name. See how foundryprovider.NewAgent snaps them into an agent.
Back the agent with Azure OpenAI's Responses API, and toggle whether conversation state lives on the server or locally.
Back an agent with Azure OpenAI Responses via NewResponsesAgent, and use DisableStoreOutput to keep chat history local instead of stored server-side.
Build a GDPR Article 22 compliant explanation endpoint in Go that turns audit logs and eval stores into regulator-friendly answers for AI decisions.
Request → N-eyes approve → window-of-time → automatic expiry, with every transition written to a hash-chained audit log. The package that closes Gap #1 from the PCSE map.
The same agent primitive, wired to Azure OpenAI's Chat Completions API where the model name is your deployment name.
Back an agent with Azure OpenAI Chat Completions via NewChatCompletionsAgent, where the Model field is your Azure deployment name, not a catalog model ID.
Reach a Foundry-hosted model through the OpenAI-compatible Responses API by configuring a plain openai.Client with three request options.
Reach a Foundry model through the OpenAI-compatible API by configuring an openai.Client with base URL, an Azure token credential, and the ai.azure.com scope.
Point the same agent at an Azure AI Foundry project endpoint using the project Responses API mode.
Run an agent against an Azure AI Foundry project: foundryprovider.NewAgent plus ModelDeployment selects project Responses API mode from the project endpoint.
Five interfaces hold the whole platform together. The 30-line orchestrator closure that makes the rest of the architecture testable, auditable, and safe to evolve.
The same agent primitive as the Foundry lessons, backed by the Anthropic (Claude) provider instead of Azure AI Foundry.
A provider swap onto Anthropic Claude: build an anthropic.Client, pass it to anthropicprovider.NewAgent, and run the identical agent surface.
PostgreSQL row-level security as HIPAA defence in depth. Why fail-open application filtering isn't enough, and how 'append-only at DB GRANTs' carries more of the §164.312(b) burden than people realise.
This lesson swaps the LLM behind an agent for another agent, reached over the A2A protocol instead of a model API.
Back a Go agent with another agent over the A2A protocol: resolve the remote card, open a gRPC client, and wrap it with a2aprovider.NewAgent.
The 21st Century Cures Act §3060 CDS carve-out criterion 4 expressed as a code-level queue, lossless on reject, with audit-recorded reviewer rationale. Build it once, satisfy GDPR Article 22 for free.
How to borrow tools from a remote Model Context Protocol server and hand them to a Foundry agent as ordinary tools.
Connect to Microsoft Learn's public MCP server with mcptool.Connect and ListTools, then hand the borrowed tools to a Foundry agent as ordinary agent.Config.Tools.
How a single sprint of specialty-rule work — guided by a benchmark that wasn't afraid to print embarrassing numbers — turned a 'demo respiratory differential' into a five-condition rule-based diagnostic engine.
How a shared state snapshot rides along with every AG-UI turn, so client and server-hosted agent stay in sync on evolving structured data.
Share a JSON state snapshot across AG-UI turns — server middleware emits a DataContent snapshot from the model's JSON and the client adopts it via toStateContent and extractState.
What HIPAA looks like when you express it as Go interfaces — governance policies, append-only audit at DB GRANTs, PHI redaction at the logger seam, and HITL as the §3060 CDS carve-out criterion 4.
How an approval-required tool makes the server pause a run and wait for a human on the client to say yes or no.
Gate a tool behind tool.ApprovalRequiredFunc so the AG-UI server pauses the run, then answer the approval from the client with a message round-trip loop.
How the server-hosted agent can call a tool that actually runs on the client, and the one flag that makes it work.
Let a server-hosted agent call a client-side tool over AG-UI — the server sets DisableFuncAutoCall and forwards the call to the client, which runs the Go function locally.
How an AG-UI-hosted agent runs a server-side function tool while the thin client just streams the conversation.
Give an AG-UI-hosted agent a server-side search_restaurants tool via functool while the thin SSE client just streams the reply — the tool round-trip stays invisible.
We built a small Go + Python service that parses a project's INFORMATION_SCHEMA, asks Gemini to classify each top-spending query against a catalog of anti-patterns, and recommends a rewrite. It is not a magic box; it is a pipeline that cuts the human review time per query from 20 minutes to 90 seconds.
How to take the same Foundry agent from earlier lessons and serve it over the AG-UI protocol so a separate client can drive it over HTTP+SSE.
Serve an unchanged Foundry agent over the AG-UI protocol with one aguiprovider.NewJSONHTTPHandler call, then drive it from a credential-free SSE client.
How a memory ContextProvider backed by an Azure AI Foundry store lets an agent recall you in a brand-new session.
Attach a Foundry-backed memory ContextProvider that retrieves before and stores after each run, so a fresh session still recalls facts keyed by a scope.
How a real shell tool lets the model run commands, and an environment provider tells it which shell it is driving.
Pair a run_shell tool with an EnvironmentProvider that probes the shell once and injects OS-correct idioms, contrasting stateless and persistent shell modes.
Notes from contributing to Google's open-source Spanner Migration Tool (HarbourBridge). Where to start reading the codebase, where the load-bearing logic lives, and the parts that look simple but aren't.
How to keep a long-running conversation inside the context window by chaining compaction strategies from gentle to aggressive.
Chain four compaction strategies from tool-result collapse to summarization to sliding window to truncation, each gated by a trigger and a preservation floor.
Spanner partitions by primary-key range. A monotonically-increasing PK like a timestamp or UUID-v1 funnels all writes to one server. The fix changes everything from your sequence strategy to your tenant model.
How a ContextProvider injects extra messages and tools into every run — a live todo list and calendar — with state that survives serialize and resume.
A ContextProvider injects a live todo list and calendar into each run and contributes session-mutating tools, with state that serializes to JSON and resumes.
How wrapping one agent as a tool.Tool lets an orchestrator agent delegate to a specialist — composition all the way down, with no routing code.
Wrap a specialist agent with agenttool.New so an orchestrator calls it like any tool, cascading two levels deep from orchestrator to weather agent to leaf function.
How one message can bundle a text prompt and an image, and why that forces RunMessage instead of the RunText shortcut.
Bundle a TextContent prompt and a base64 DataContent image into one message.Message and run it with RunMessage instead of the text-only RunText shortcut.
How to publish an agent as a discoverable tool on a Model Context Protocol server so any MCP client can invoke it.
Wrap an agent with agenttool.New then register it with mcptool.AddTool to serve it over MCP on stdio, so any MCP client can discover and invoke it.
How Go's constructor-over-an-interface idiom lets you inject a real Foundry agent into a service — and a fake into its test — through the same seam.
Inject a Foundry agent into a service through a two-method ChatAgent interface, so main injects the real agent and the test injects a fake through the same constructor.
How to turn every agent run into an OpenTelemetry span with the SDK's otelprovider middleware.
Wire otelprovider.NewMiddleware into agent.Config.Middlewares to open a gen_ai span around every run, exported to whatever TracerProvider you register globally.
How to teach an agent to load and persist conversation memory in your own store via a custom history provider.
Implement a custom agent.HistoryProvider with Provide and Store hooks so the agent loads and persists history in your store; DisableStoreOutput keeps it the single source of truth.
The Picnic social platform served 1M+ users across a graph of Go microservices behind a GraphQL gateway. The latency win came from a counter-intuitive move: fewer services, tighter contracts.
How to serialize an agent.Session to storage and resume the same conversation later, even from a new process.
Serialize an agent.Session with encoding/json, store the bytes, and reload them into a fresh Session in another process to resume the exact same conversation.
Test coverage and observability are the boring infrastructure that makes the interesting changes safe. Notes on how the Picnic team built both, and the on-call experience they enabled.
How to make the agent return a typed Go struct instead of free-form prose, via a JSON schema derived from your type.
Two ways to get typed output from an agent: per-run agent.WithStructuredOutput, or agent.WithResponseFormat with jsonformat.MustFor baked into Config.RunOptions.
The transaction engine had to absorb 30K+ TPS across partner integrations, never lose a transaction, and survive partial failures. The architecture: Go, Kafka, Pub/Sub, Redis, K8s, with idempotency at every layer.
How to pause a run for human approval before the framework is allowed to execute a tool.
Wrap a tool with tool.ApprovalRequiredFunc so the run pauses and returns a ToolApprovalRequestContent; approve or decline, then resume with RunMessage on the same session.
A single layer of idempotency will eventually fail. Three independent layers gives you a margin. Here is the pattern that worked across ingest, worker, and emit boundaries.
How to wrap a plain typed Go function as a tool the model can call mid-run.
Wrap a plain typed Go function with functool.MustNew and attach it via agent.Config.Tools so the model can call it; the SDK infers the JSON schema from the signature.
Status-code-based dispatch made every worker grow a longer and longer switch. Normalising every partner-specific error into an enumerated set let the orchestration logic stop changing as new partners landed.
How an agent.Session carries conversation history across RunText calls so the model remembers earlier turns.
Thread conversation history across RunText calls with an agent.Session and agent.WithSession, so a follow-up prompt builds on the previous turn; a new session starts fresh.
5K+ loans per month. Three credit bureaus. Multiple payment gateways. The thing that has to be right is the ledger. Notes on what invariants the database enforces vs what the application enforces.
How to wrap every agent run with a middleware — the standard hook for logging, tracing, and guardrails.
Wrap every agent run with an agent.Middleware in the Foundry Go SDK: one pass-through function that observes messages and updates without altering the result.
How to resume a long-running remote agent stream after it drops — using a continuation token to reconnect instead of re-sending the expensive query.
Capture the continuation token from a streamed remote run, then reconnect with WithContinuationToken and no messages to resume the same task to completion.
100K+ votes, 10K+ concurrent users during a live AFL Brownlow Medal broadcast. The architecture: Go on Cloud Run, GraphQL + gRPC behind a CDN, vote integrity through Cloud KMS + Security Command Center. Notes on what makes a live-broadcast load shape unusual.
How to pin which transport a client uses when a remote A2A agent advertises several bindings at once.
Pin the transport an A2A client uses via PreferredTransports so binding negotiation is deterministic, while the wrapped remote agent stays a plain agent.Agent.
How to drive a slow remote agent that answers with a continuation token, then poll that token to completion instead of blocking on one long call.
Ask a remote A2A agent with AllowBackgroundResponses, get a continuation token, and poll with WithContinuationToken and no messages until the token clears.
How to discover a remote A2A agent's advertised skills and hand each one to a local host agent as an ordinary function tool.
Resolve a remote A2A agent card, turn each advertised skill into a function tool with derived names and descriptions, and hand them to a local Foundry host agent.
What it actually takes to build a unified cloud API library — and why "write once, run anywhere" still doesn't quite work, even for the patterns where it almost does.
The other primitive: a directed graph of executors wired by edges, running fully offline with no model, no credential, no Foundry.
Wire two executors into an uppercase to reverse pipeline with the fluent workflow builder and run it fully offline via inproc.Default, iterating ExecutorCompletedEvents.
Every Professional Cloud Security Engineer exam bullet, mapped to a file path in an RBI FREE-AI aligned Go platform. Where the implementation matches, where the analog substitutes, and where the honest gaps are.
A custom ContextProvider gives the agent memory: it reads stored facts before a run and learns new ones after — all through the Session.
A custom ContextProvider wires Provide and Store hooks around every run so the agent reads remembered facts before the call and learns new ones after, all in the Session.
One Session threaded through every call turns two stateless one-shots into a single conversation that remembers.
Thread one agent.Session through every RunText call with agent.WithSession to turn stateless one-shots into a single conversation that remembers.
Hand the agent a plain Go function it can decide to call mid-conversation — the model requests it, the framework runs it, the result flows back.
Register a plain Go function as a tool with functool.MustNew; the model decides when to call it, the framework runs it, and the result flows back into the answer.
The smallest useful agent: give a model instructions and a name, hand it a message, get a response — collected or streamed.
Build the smallest useful agent from instructions and a model, then run the same RunText call two ways — collected all at once and streamed token-by-token.
The zero-network preflight that confirms your Foundry config and Azure credential chain exist before you run a single agent.
A zero-network preflight that confirms your Foundry endpoint, model deployment, and Azure credential chain exist before you run a single agent.
Stdlib over libraries, single binary over framework, fail-closed defaults over forgiveness. The boring-on-purpose case for choosing Go to ship a multi-agent system into a regulated environment.
Microsoft's Multi-Agent Reference Architecture in Go. Protocol, registry, bus, governance, orchestration, observability, evaluation — and how the seven hold each other up.
Passkeys are FIDO2; FIDO2 is the spec; Ed25519 is the signature algorithm. The full registration + assertion flow in 200 lines of stdlib Go.
Two signals do most of the work for detecting compromised sessions: impossible travel between consecutive logins, and credential-stuffing density across an IP range. The Go implementation.
Google's A2A spec standardises how agents talk to other agents (not just tools). The Go client is small; the conceptual shift is what matters.
A saga is fine when every step succeeds. The interesting code is what runs when step 3 of 5 fails and you have to undo 1 and 2 in the right order. The patterns I use.
Postgres over the latest vector DB. Go stdlib over the framework du jour. Single binary over Kubernetes operator. The choices that bore reviewers and delight on-call engineers.
Go's embed.FS bundles files into the binary at compile time. The pattern collapses what would be a multi-artefact deploy into one binary. Three places it pays back daily.
GOMEMLIMIT tells the Go runtime to keep memory below a soft cap by running GC harder when it's close. For containers with hard memory limits, this prevents OOM kills. The setting every Go service in K8s should have.
Patterns I confidently recommended five years ago that I'd argue against today. The list of "things you used to do in Go that don't pay back anymore."
Range-over-function landed in Go 1.23. `iter.Seq` lets you write iterators that compose. The patterns that pay back; the ones that don't.
Fan out to N agents; first error cancels the rest; collect successful results. errgroup is the right tool for this; the patterns are concise but worth getting exactly right.
An honest retrospective on the open-source Genie project after a year. The patterns that held up; the ones we rebuilt; the code we deleted because it solved problems we didn't actually have.