« Phase 23 README · Warmup · Hitchhiker's · Deep Dive · Principal Deep Dive · Core Contributor
Phase 23 — Staff Engineer Notes: AutoGen & the Microsoft Agent Framework
Using a framework is knowing its API. Owning it is knowing which decisions are yours, which defaults are traps, and what you are on the hook for when it breaks at 3 a.m. This document is about the judgment layer — the calls a staff engineer makes that a mid-level engineer does not know are calls at all.
The decisions you actually own
Open-ended team vs explicit Workflow — per task, not per project. This is the decision. The junior instinct is "multi-agent, so AutoGen team." The staff instinct is MSAF's own principle: "if you can write a function, do that." Autonomy is a cost, not a badge (Phase 00). You default to an explicit Workflow — typed edges, checkpointing, HITL, auditability — and you reach for an open-ended team only for the sub-task that genuinely cannot be enumerated in advance. In the wholesale-banking scenario, exactly one step (reading a fuzzy customer email) is open-ended; triage-decide-draft-approve is an explicit Workflow with a RequestInfoExecutor on anything that moves money. Being able to draw that boundary — this box is an agent, everything else is a graph — is the senior artifact.
Which orchestration pattern. You own naming the shape, because naming it is choosing its failure mode and its bound:
- Sequential — cheapest, most auditable; it is really a workflow. Default for known pipelines.
- Concurrent — fan-out to independent branches, fan-in through an aggregator; the aggregator (join, majority vote, all-must-approve) is where the real logic lives.
- Handoff — dynamic transfer to a named agent; you own that the target is validated and the chain is bounded.
- Group-chat — the AutoGen team; most emergent, least predictable; reach for it last.
- Magentic — manager + progress ledger; the general orchestrator that subsumes the others, bounded by
max_rounds. Reach for it when the task is genuinely open-ended and multi-specialist.
Framework selection. MSAF vs LangGraph vs OpenAI Agents SDK vs CrewAI, on real axes — explicit-graph-vs-open-ended, checkpointing/HITL, type safety, and ecosystem/language. MSAF and LangGraph are close cousins (both graph workflows on a super-step runtime with checkpointing and HITL); MSAF adds type-safe edges and a first-class agent/thread/session model and lives in the .NET + Python + Go / Azure world with SK's plumbing, while LangGraph is Python/JS-first with the richest checkpointer/store ecosystem. The OpenAI Agents SDK is lighter — Agent + Runner + handoffs + guardrails, no built-in graph/typed-edges/durable-checkpointing. CrewAI is role/task-centric and fast to start, thin on typed orchestration and durability. The staff answer names the axis that matters for this task and the ecosystem you are in — never "it depends" without saying on what.
Being current is itself a seniority signal
The single most current-sounding sentence in a Microsoft-stack round: "MSAF is the successor to both AutoGen and Semantic Kernel." "I'd use AutoGen for the multi-agent part and Semantic Kernel for the enterprise integration" was a good 2024 answer and is now a stale one — it tells the interviewer you stopped tracking the field a year ago. The correct framing is "I'd build on the Microsoft Agent Framework; its Workflow engine gives me typed, checkpointed orchestration, and its agent abstractions cover the conversational part; AutoGen and SK are the lineage the mechanisms come from." Same concepts, current packaging. Tracking the field is part of the job at this level.
Code-review red flags
These are the things that make me stop a review and ask a question:
- A team with no
MaxMessageTerminationbackstop. ATextMentionTermination("APPROVE")alone is not a bound — the model can almost approve forever. Every team composes a max backstop with|. Termination is the team-levelmax_steps; the keyword is a suggestion, the max is the guarantee. - An unvalidated handoff target. A transfer to a name that is not checked against the roster is a routing bug that fails silently. The target must be validated to exist; an unknown handoff should raise, not no-op.
- The type used as a router. If an edge branches by matching on message type instead of a
condition, a type mismatch becomes a silently dropped message instead of aWorkflowTypeError. The type is a contract that errors; the condition is the router that selects. Conflating them is the most dangerous line in a Workflow. - A Workflow with no
max_supersteps. A cyclic graph with no super-step bound is a non-halting program. Same bug as the unbounded team, wearing a graph costume. - A side-effecting node with no idempotency key. The durable store will replay on resume. If the node sends an email or moves money and is not keyed by an operation id, resume duplicates the effect. "What happens if this runs twice?" is the first question for any node with a side effect.
- HITL and checkpointing treated as two features. If a design has a bespoke "wait for human" path separate from its persistence, it has doubled the state to secure and back up, and probably gotten one of them wrong. They are one mechanism — a pause at a super-step boundary.
Production war stories
- The group chat that never stopped. A reviewer/writer team with only a keyword termination; the model kept nearly approving. Ran until the token-budget alarm fired. Fix: compose a
MaxMessageTerminationwith|. The lesson is structural — a missing bound is not a slow program, it is a non-halting one, and it bills you the whole way. - The stringly-typed handoff that shipped garbage. Agent A emitted a dict, agent B expected a list; nothing errored, B produced nonsense that surfaced three steps downstream. This is the exact bug MSAF's typed edges catch at the wiring — a
WorkflowTypeError, not a corrupted run. - The refund nobody approved. A "workflow" that continued past a human-approval step when the approval service timed out and returned empty; the re-run re-sent the refund because the step was not idempotent. MSAF's answer: the HITL node checkpoints and pauses, and
resumerequires the response or raises. Treating HITL as optional is how money moves without a human.
The signal an interviewer is listening for
Not whether you can list AssistantAgent, RoundRobinGroupChat, and WorkflowBuilder — anyone who read the quickstart can. The signal is whether you reach for the least-agentic thing that works, whether you name bounds and validation unprompted, and whether you can state the two insights that separate a builder from a user: that HITL and durable checkpointing are the same mechanism (a pause at a super-step boundary), and that an edge's type is a contract that errors while its condition is the router — and why conflating either pair is a real bug, not a style nit. When an architecture review hears you say "that's a handoff pattern, bounded, with a validated target" or "the type raises, the condition routes," it hears someone who has owned one of these in production, not someone who demoed one.
Closing takeaways
- Default to explicit, escape to open-ended. The Workflow is the default; the agent is the exception you justify per sub-task. "If you can write a function, do that" is the whole phase in one line.
- Every loop carries a bound, every route validates its target.
MaxMessageTermination,max_steps,max_rounds,max_supersteps— a multi-agent system without a step budget is infinite ping-pong; an unvalidated handoff is a silent routing bug. - HITL and durability are one feature; side effects must be idempotent because the store will replay. The doubled refund is the canonical failure; the idempotency key is the canonical fix.
- The type errors, the condition routes — keep them separate. Conflating them turns a caught correctness bug into a silently dropped message.
- Say "MSAF is the successor to both AutoGen and Semantic Kernel." It is current, it is correct, and it signals you track the field — which at staff level is part of the job.
- Name the axis and the ecosystem when you choose a framework. MSAF vs LangGraph vs Agents SDK vs CrewAI is decided by typed/durable/governed control-flow needs and by whether you live in Azure/.NET, Python/LangChain, or the OpenAI stack — not by a feature-count contest.