#AI Agents

Articles about AI Agents — exploring patterns, best practices, and real-world implementations in production systems.

232 posts tagged with ai agents. ← All posts

A2A (5)ADK (8)AG-UI (7)AI Agents (232)AI Governance (5)Agent Skills (3)Agentic AI (13)Agents (4)Architecture (15)Azure (9)Azure AI Foundry (10)BigQuery (6)Checkpointing (5)Compliance (8)Concurrency (4)Context Providers (3)Conversation State (3)Cost Optimisation (3)Distributed Systems (3)Evaluation (4)FREE-AI (8)FinOps (5)FinTech (6)Function Tools (6)GCP (5)Go (168)Google ADK (26)Governance (5)Guardrails (3)HIPAA (3)Harness Engineering (8)Human-in-the-Loop (7)KYC (3)Kubernetes (6)LangGraph (11)Microsoft Agent Framework (21)MCP (5)Memory (5)Microsoft Agent Framework (188)Middleware (9)Multi-Agent (8)Multi-Agent AI (13)Multimodal (4)Observability (12)Open Source (6)OpenTelemetry (5)Opinion (6)Orchestration (15)Payments (4)Privacy Engineering (3)Providers (3)Python (126)RAG (6)RBI (3)Retrieval (3)SRE (3)Security (9)Sessions (4)Spanner (4)Streaming (4)Structured Output (4)Workflows (14)
Pratik Dhanave · ·7 min read

Human-in-the-Loop: An Approval Gate on Durable State

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.

Pratik Dhanave · ·7 min read

Hierarchical Supervision: Bounded Fan-Out, Ordered Fan-In, Fault Isolation

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.

Pratik Dhanave · ·6 min read

Advanced Memory: Threads, Keyword Retrieval, and Lossy Summarization

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.

Pratik Dhanave · ·7 min read

Secure Sandboxing: Running Agent-Written Code Behind a Timeout

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.

Pratik Dhanave · ·9 min read

Durable Execution: Checkpoint Every Step, Resume After a Crash

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.

Pratik Dhanave · ·7 min read

The Agent Harness: guardrails as middleware around the model

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.

Pratik Dhanave · ·5 min read

Human-in-the-Loop, Tools, and the Send API

The higher-level building blocks LangGraph stacks on top of the graph engine — pausing for a human, running an agent loop, calling tools, and fanning out dynamically.

The building blocks on top of the core graph: interrupt() to pause for human input, create_react_agent and ToolNode for tool-using agents, and the Send API for dynamic parallel fan-out with a reducer fan-in.

Pratik Dhanave · ·2 min read

AG-UI State Management: The Server

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.

Pratik Dhanave · ·6 min read

Harness Engineering in Go: build the harness, then let Azure supply it

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.

Pratik Dhanave · ·5 min read

Streaming: values, updates, and debug Modes

Watching a LangGraph run happen — the three things `.stream()` can show you, and why they fall out of the superstep model for free.

stream() exposes a run in three modes: values (full state after each node), updates (what each node changed), and debug (the raw event stream). Streaming falls out naturally from the superstep model.

Pratik Dhanave · ·6 min read

Cycles and the Agent Loop: Branch, Act, Loop Back

The single most important pattern in LangGraph — a branch plus a back-edge, and the `recursion_limit` that keeps it from running forever.

Branching plus a back-edge is a cycle, and that cycle IS the agent loop: model proposes tool calls, tools run, control returns to the model, repeat until done. Plus recursion_limit, the guardrail that stops a runaway loop.

Pratik Dhanave · ·6 min read

Grounding & RAG in ADK: Answers Anchored in Real Data

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.

Pratik Dhanave · ·2 min read

A2A Server

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.

Pratik Dhanave · ·2 min read

A2A Client

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.

Pratik Dhanave · ·5 min read

Callbacks in Google ADK: Six Hooks and One Rule

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.

Pratik Dhanave · ·5 min read

Artifacts: Where ADK Agents Put Their Files

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.

Pratik Dhanave · ·2 min read

03 · Agent Workflow Patterns (sequential · concurrent · group chat)

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.

Pratik Dhanave · ·2 min read

step03 · Mixed Skills

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.

Pratik Dhanave · ·2 min read

Devui

Giving any agent a local chat window plus a live call inspector with agent_framework.devui.serve.

DevUI wraps any Foundry agent in a local chat window plus a live inspector via serve(entities=[agent]) from the separate agent-framework-devui package.

Pratik Dhanave · ·1 min read

Magentic

For open-ended tasks with no known solution path: a manager agent plans, keeps a shared ledger, and round-by-round picks which specialist acts next. Ordering is dynamic, not a fixed graph.

Magentic orchestration puts a manager agent in charge: it plans, keeps a shared ledger, and picks which specialist acts next round by round until it synthesizes an answer.

Pratik Dhanave · ·1 min read

Group Chat

A collaborative conversation among agents, coordinated by an orchestrator that decides who speaks next. Agents share full history and refine each other's work over rounds — a star topology.

Group chat coordinates several agents in a star topology: an orchestrator decides who speaks next while agents share full history and refine each other over rounds.

Pratik Dhanave · ·1 min read

Handoff

A mesh of specialists where any agent can transfer the whole conversation to a better-suited peer — no central orchestrator. Control passes agent-to-agent via an auto-injected handoff tool call.

Handoff orchestration lets any agent transfer the whole conversation to a better-suited peer via an auto-injected tool call. Run unattended with autonomous mode.

Pratik Dhanave · ·1 min read

Concurrent

Run several agents on the same prompt in parallel, then fan their answers back in. `ConcurrentBuilder` wires the fan-out/fan-in graph — latency is max(agent), not sum.

Concurrent orchestration fans one prompt out to several agents in parallel, then fans their answers back in with a built-in aggregator. Latency is max(agent), not sum.

Pratik Dhanave · ·1 min read

Sequential

Wire agents into a pipeline where each runs in turn and feeds the next. Hand a list to `SequentialBuilder`, call `.build()`, run it once — draft then review, extract then summarize.

Sequential orchestration chains agents so each runs in turn and feeds the next. Hand a list to SequentialBuilder, build, and run once — draft then review.

Pratik Dhanave · ·2 min read

Sub Workflows

A whole workflow run as a single executor inside a parent. Wrap the inner graph in `WorkflowExecutor`, drop it into the parent like any node, and compose big systems from small, testable pieces.

Run a whole workflow as one executor inside a parent: wrap the inner graph in WorkflowExecutor, line up its I/O types, and drop it into the parent like any node.

Pratik Dhanave · ·2 min read

Resettable Executors

Executor state leaks when you reuse one workflow across independent runs. `.NET` has `IResettableExecutor`; Python's answer is simpler — never share state, build fresh instances from a factory.

Reusing one workflow across runs leaks executor state. .NET has IResettableExecutor; Python's answer is a factory that builds fresh workflow and executor instances per run.

Pratik Dhanave · ·2 min read

Execution Modes

The same `workflow.run(...)` graph, consumed two ways — await it to completion, or stream its events live. The `.NET` OffThread/Lockstep modes don't apply to Python.

One workflow.run graph, two modes: await it to completion or iterate stream=True live events. The .NET OffThread/Lockstep modes do not apply to Python.

Pratik Dhanave · ·1 min read

Agent Executor

Wrapping agents as AgentExecutors explicitly — controlling the id, the context mode, and chaining a writer to a translator that sees only the previous agent's reply.

Wrap agents explicitly as AgentExecutors to set the id and context_mode. last_agent mode feeds a downstream agent only the previous reply, ideal for translate and refine.

Pratik Dhanave · ·1 min read

Visualization

WorkflowViz renders a built workflow's graph as a Mermaid diagram, a Graphviz DOT string, or an exported image — so you can eyeball fan-out/fan-in structure without running the agents.

Render a built workflow with WorkflowViz as Mermaid or Graphviz DOT, or export an image. Text formats need no deps; visualization reads graph shape without calling agents.

Pratik Dhanave · ·1 min read

Workflow Observability

Turn a workflow run into a tree of OpenTelemetry spans — workflow.build, workflow.run, executor.process, edge_group.process, message.send — with one setup call.

Trace a workflow with configure_otel_providers and a root span. The framework emits workflow.build, workflow.run, executor.process, edge_group.process, message.send spans.

Pratik Dhanave · ·2 min read

Events

Streaming a workflow run so you can watch progress live — built-in lifecycle events plus your own custom ones — all discriminated by a single `.type` string.

Stream a Microsoft Agent Framework workflow with run(stream=True). Every event is one WorkflowEvent keyed by a .type string, plus custom events via ctx.add_event.

Pratik Dhanave · ·2 min read

Human In The Loop

Some steps need a person — request_info suspends the workflow and hands control back to your code, then you resume by re-running with the human's answer keyed by request_id.

request_info suspends the workflow and returns a pending request; you resume by re-running with the human's answer keyed by the same request_id.

Pratik Dhanave · ·2 min read

Frontend Tools

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.

Pratik Dhanave · ·2 min read

Checkpointing

Long or human-gated workflows can't live only in memory — hand the builder a CheckpointStorage and it snapshots state after each superstep, so you can restore and resume.

Hand the builder a CheckpointStorage and it snapshots state after each superstep, so you can list saved checkpoints and resume from an id.

Pratik Dhanave · ·2 min read

Backend Tools

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.

Pratik Dhanave · ·2 min read

Parallelism

The reason to reach for a graph over a chain: fan out work to run concurrently, then fan in to merge — wall-clock is the slowest worker, not the sum.

Fan-out broadcasts the same message to concurrent workers; fan-in gives a joiner a list of all outputs and fires once every source completes.

Pratik Dhanave · ·2 min read

Hosted Mcp

Point an agent at a remote MCP server and let Foundry do the calling — you describe the server once, the service discovers and invokes its tools for you.

A hosted MCP tool aims the agent at a remote MCP server and lets Foundry connect and call it; you describe the server once and set an approval mode.

Pratik Dhanave · ·2 min read

Web Search

Let an agent reach live search results for anything past its training cutoff — Foundry runs the search and grounding server-side, and returns URL citations.

The hosted web search tool lets an agent reach live results past its training cutoff; Foundry searches and grounds server-side and returns URL citations.

Pratik Dhanave · ·2 min read

File Search

Ground an agent's answers in documents you upload — the provider indexes them into a vector store and searches server-side, no retrieval code of your own.

File search is a hosted tool: upload files, index them into a vector store, and bind the agent to the store id so Foundry runs retrieval server-side.

Pratik Dhanave · ·1 min read

Code Act

Letting the agent write and run one Python program instead of looping tool-by-tool.

CodeAct adds a single execute_code tool so the agent writes one sandboxed Python program calling tools via call_tool, wired through the Hyperlight provider with a fallback to direct tools.

Pratik Dhanave · ·2 min read

05 · First Workflow

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.

Pratik Dhanave · ·1 min read

Harness

The batteries-included autonomous agent pipeline from create_harness_agent.

Assemble a batteries-included autonomous agent with create_harness_agent: a function-calling loop, todo list, plan/execute modes, and compaction, each individually switchable via disable flags.

Pratik Dhanave · ·2 min read

04 · Memory

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.

Pratik Dhanave · ·1 min read

Skills

Packaging reusable agent capabilities that load lazily via progressive disclosure.

Package reusable agent capabilities as skills: define an InlineSkill with frontmatter, resources, and scripts, attach via SkillsProvider, and let the agent load them lazily on demand.

Pratik Dhanave · ·1 min read

Evaluation

Scoring Microsoft Agent Framework agent outputs offline with a LocalEvaluator.

Score Microsoft Agent Framework agent outputs with evaluate_agent and a LocalEvaluator: run offline keyword, tool-call, and custom evaluator checks, then gate CI via raise_for_status.

Pratik Dhanave · ·2 min read

02 · Add Tools

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.

Pratik Dhanave · ·2 min read

01 · Hello Agent

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.

Pratik Dhanave · ·1 min read

Rag

Grounding a Microsoft Agent Framework agent in your own docs with a search tool.

Ground a Microsoft Agent Framework agent with RAG-as-a-tool: expose a search function over your docs, instruct the agent to retrieve then answer and cite, and decline when nothing matches.

Pratik Dhanave · ·1 min read

Security

Defending against prompt injection with information-flow control over trusted and untrusted content.

Defending a Microsoft Agent Framework agent from prompt injection with SecureAgentConfig, information-flow labeling of untrusted content, and block_on_violation enforcement.

Pratik Dhanave · ·1 min read

Mcp Tools

Borrowing tools from an external MCP server instead of writing them yourself.

Connecting a Microsoft Agent Framework agent to an external Model Context Protocol server via MCPStdioTool, entered with async with, so its remote tools merge into tools=[...].

Pratik Dhanave · ·1 min read

Middleware

Wrapping an agent run to observe, guard, or short-circuit it — without touching the agent's logic.

Agent, chat, and function middleware in Microsoft Agent Framework: one middleware=[...] list, call_next() with no args, and short-circuiting via MiddlewareTermination.

Pratik Dhanave · ·1 min read

Host Your Agent

Everything so far ran once and exited. To use an agent like a product, put a server in front of it — DevUI stands up a local web chat around any agent with one call.

serve() from agent_framework.devui wraps any agent in a local web chat; it blocks with its own event loop and ships as a separate install.

Pratik Dhanave · ·1 min read

First Graph Workflow

The functional API hid the graph. Here it's explicit: executors are nodes, edges join them, and a message flows from the start executor along the edges.

Build a two-node graph with WorkflowBuilder: executors send_message or yield_output, and the type hint on WorkflowContext carries the routing intent.

Pratik Dhanave · ·2 min read

Multi Turn

An Agent is stateless — two runs are strangers. What carries history from one turn to the next is an AgentSession.

An Agent is stateless; an AgentSession carries history between turns. Thread create_session() through each run so turn two can see turn one.

Pratik Dhanave · ·2 min read

Add Tools

A tool is just a Python function the model may call: decorate it with @tool, annotate the arguments, and the framework wires the schema, the call, and the result back into the conversation.

Turn a Python function into a tool with the @tool decorator and Annotated Field descriptions, then let the model pick the right one from the question wording.

All posts on this site are written by Pratik Dhanave, an Agentic AI Architect with 7+ years building production distributed systems, multi-agent AI platforms, and cloud-native infrastructure. About the author → Each article includes working code, architecture diagrams, and references to the specific frameworks and standards discussed. Browse all posts or explore related topics using the tag cloud above.