Microsoft Agent Framework Go
Open-source contributions to microsoft/agent-framework-go — the official Go implementation of the Microsoft Agent Framework for building AI agents and multi-agent workflows. My work targets runtime correctness and safety hardening: concurrency and data-race fixes, nil-safety and panic guards across the model providers, streaming-protocol correctness, and request-path validation — each landed with a regression test that fails before the change and passes after.
About the framework
The Microsoft Agent Framework is Microsoft's open-source framework for building AI agents and orchestrating multi-agent workflows, with a provider layer spanning OpenAI, Anthropic, Azure OpenAI, and Azure AI Foundry. agent-framework-go is its Go implementation. My contributions span the agent runtime and middleware (tool approval, agent mode, skills), the workflow routing engine, and the model providers — the kind of concurrency- and stream-sensitive code where a missing guard surfaces only under real parallel tool use.
The two authored reference implementations on my portfolio — Genie Project (multi-agent financial assistant) and Bodh (medical diagnostic panel) — are built on this framework, which is what surfaced these upstream issues in production.
Merged
Accepted upstream into main.
Nil updates are legal in a response stream — the agent run loop skips them and the toolautocall middleware forwards them — but toolapproval dereferenced every update, so composing the two panicked with a SIGSEGV. The fix forwards nil updates downstream, preserving stream semantics. Shipped with a passthrough regression test that fails on main and passes after.
AddHandlerRaw guarded against registering a typed handler for PortableValue, but reflect.TypeOf(messageType) on an already-reflect.Type value made the check dead code (always false), so colliding handlers were silently accepted. Compares the reflect.Type by value instead, matching the package's own idiom, with a test asserting rejection.
Open
Proposed fixes under review.
The non-streaming Chat Completions path indexed resp.Choices[0] unconditionally. Some OpenAI-compatible services return HTTP 200 with an empty choices array — notably Azure OpenAI when a content filter blocks the prompt — panicking with index out of range. Returns an error through the response stream instead, mirroring the guard the streaming path already had.
The agentmode provider read and wrote session state with no synchronization. toolautocall runs multiple tool calls from one model response on separate goroutines when concurrent invocations are enabled, so mode_set/mode_get raced on the session map. Adds per-session mutexes — mirroring the sibling todo provider — with a -race test.
fsskills honored Source.searchDepth for within-skill file scanning but hardcoded skill-directory discovery to depth 2, so raising SearchDepth silently ignored more deeply nested skill directories. Threads the configured depth into discovery and documents the widened scope, with a test covering a four-levels-deep skill directory.
Closed
Filed to make an issue concrete; superseded or deferred to maintainer preference. Included for a complete record.
Two streaming bugs broke parallel tool use: every content_block_stop re-emitted all accumulated function calls (executing the first tool call repeatedly), and argument JSON was seeded with the {} input placeholder so deltas produced {}{"city":"Paris"}. Emits each call once on its block stop and accumulates input_json_delta fragments from scratch.
The Azure AI Projects toolbox request builders interpolated a caller-supplied name directly into the request path. A name that isn't a single intact segment (./.. traversal, or a raw / percent-encoded separator) could alter the request target. Ports the upstream .NET EnsureSafeToolboxName validation to Go, validating the raw and percent-decoded name.
Explore more
See the full open-source record, or the multi-agent systems built on this framework.