The Smallest Useful Unit: A Conversable Agent

For AutoGen, the key design question is what must be shared by an LLM, a person, and a tool before they can participate in one workflow. The answer is the conversable agent: a component with a role, conversation context, and a reply boundary. Understanding that unit lets the reader inspect an AutoGen system by asking who owns a decision, what information crosses the boundary, and what kind of capability produces the next response.

A role with memory and a reply boundary

A conversable agent is not defined by having a human-like personality. It is an entity that can send and receive messages, maintain context from those messages, and respond according to a configured role and set of capabilities. The role matters because a complex task becomes manageable only when the system can distinguish responsibilities. “Suggest a solution,” “execute the proposed code,” “ask a person for clarification,” and “validate the result” are different jobs even when they contribute to the same answer.

The agent’s conversation context is the working state that makes a reply more than an isolated completion. A newly received message may contain a request, an earlier agent’s proposal, an error, or an observation from the outside world. The agent combines that message with relevant history before deciding how to respond. If an assistant proposes a program and receives an execution error, the error is not merely another sentence to quote. It is information that should condition the next proposal. If a proxy receives a request for human input, the person’s answer becomes part of the context that the assistant uses to continue.

This context has two dimensions that are easy to conflate. One is persistence across turns: the agent needs enough history to understand what the current message means. The other is scope: it should not automatically inherit every message exchanged elsewhere. A coding assistant may need the user’s question and the executor’s output, while a safety checker may need the proposed operation and relevant policy context but not every exploratory exchange. The source paper describes agents as maintaining internal context based on sent and received messages; the engineering consequence is that context selection is part of the design, not an incidental property of chat.

That is also why context should be treated as owned state rather than as a transcript that everyone automatically shares. Passing a message across an interface exposes the information needed for the next responsibility without requiring every agent to inherit every internal detail. The separation can reduce distraction and make a component easier to test. It can also create a failure if the receiving agent lacks a fact needed to interpret the message, so the boundary must be designed around the task rather than around a slogan about modularity. A short message such as “the code failed” is not enough if the receiver cannot tell which code, in which environment, and with what error.

The common interface is therefore a behavioral contract. Sending passes an item of work or information to another participant. Receiving makes the agent responsible for deciding what to do with it. Reply generation turns the current context and capabilities into a response, which may be language, a request for input, a tool call, an execution result, or a termination signal. The exact implementation can vary, but the system needs these responsibilities to remain legible. When a result is wrong, someone should be able to ask whether the error arose in the proposed computation, the information supplied to it, the tool that acted, or the decision to continue.

A boundary is useful only when the system can observe what crosses it. In an AutoGen conversation, that crossing may be a natural-language proposal, structured information produced by a function, feedback from code execution, or an answer supplied by a human. The recipient does not receive the sender’s entire internal reasoning; they receive a message that must be sufficient for their assigned response. This makes message design a form of interface design. Vague messages create hidden coupling because the receiver must reconstruct missing assumptions. Overloaded messages create a different problem: the receiving agent may treat an incidental remark as an instruction. A conversable agent is therefore a small runtime component, but its contract has system-wide consequences.

A useful way to visualize the abstraction is to separate the common conversational shell from the capability that powers a response:

classDiagram class ConversableAgent { role conversation_context send(message) receive(message) generate_reply() } class AssistantAgent class UserProxyAgent class LLM class Human class Tool ConversableAgent <|-- AssistantAgent ConversableAgent <|-- UserProxyAgent ConversableAgent --> LLM : may use ConversableAgent --> Human : may solicit ConversableAgent --> Tool : may invoke Tool --> ConversableAgent : execution feedback Human --> ConversableAgent : judgment or input

The diagram does not claim that every agent uses all three backends, or that the backends are interchangeable in their behavior. It shows the point of the abstraction: the conversation interface remains stable while the source of a response changes. A tool can return a deterministic observation; a human can return a judgment; an LLM can infer, draft, or revise. AutoGen’s framework can place these different sources behind agents that communicate in a common way.

That common shell gives a system a place to attach control. A message is not just a payload moving between independent programs. Its arrival can trigger a reply, and the reply can create the next piece of work. The agent receiving an execution result may generate a correction. The agent receiving a person’s answer may resume a paused task. The agent receiving a termination condition may stop instead of producing another turn. The shell is small, but it connects state, capability, and transition.

The distinction between role and capability is important here. A role says what responsibility the agent has in the workflow; a capability says what the agent can use to discharge it. An assistant may have the role of proposing a solution and an LLM capability for doing so. A user proxy may have the role of mediating between the system and its environment, with human input and code execution available. A specialized application can assign the same broad capability to a different role, or give one role several capabilities. Keeping the concepts separate allows a workflow to change the backend without silently changing who is accountable for the decision.

One interface, different kinds of capability

AutoGen identifies three broad sources of agent capability. An LLM-backed agent can use conversation history to infer state, play a role, generate code, respond to feedback, and adapt its proposal. A human-backed agent can request input at selected points, with configurable rules about when participation is required and whether the person may skip a turn. A tool-backed agent can execute code or function calls. These sources can be combined, but they should not be confused.

An LLM is good at producing a candidate interpretation or plan, but its output is still a proposal until an appropriate mechanism checks or executes it. A tool can calculate or act without possessing the language model’s broad reasoning ability, but it generally needs someone else to decide which action to invoke and how to interpret the result. A person may resolve ambiguity or supply expertise that the model lacks, while introducing a dependency on availability and attention. Assigning each capability to a clear conversational participant makes these differences explicit instead of forcing one component to imitate all of them.

The built-in assistant and user-proxy arrangements illustrate the division. The assistant is configured primarily to use an LLM for problem solving. The proxy can solicit human input and execute code or function calls. In a simple interaction, the assistant receives a task and proposes a solution, perhaps including code. The proxy either asks the person for input or executes the proposed work, then returns the result. The assistant sees that result in the continuing conversation and can correct the proposal, explain it, or end the exchange. The loop joins reasoning to action without pretending that reasoning and action are the same capability.

The arrangement also assigns a useful place to failure. If the assistant’s code does not run, the proxy can return the execution error instead of silently treating the attempt as success. If a person supplies a correction, that input can become evidence for a revised response. If the tool is unavailable or the response format is unusable, the failure can be attributed to the relevant boundary. This attribution is not merely a debugging convenience. It determines whether the remedy is a better prompt, a different capability, a clearer message, or a hard constraint around execution.

The pattern can operate at different levels of autonomy. If human input is required, the proxy becomes a deliberate pause in the workflow: the system cannot proceed until a person responds or chooses to skip. If human participation is disabled, the proxy can function mainly as a tool executor. The boundary has not vanished; the source of the response at that boundary has changed. This is why “autonomous” is a configuration of a workflow, not a permanent property of an agent. A system can begin with people present at every important turn while prompts, error cases, and handoffs are being tested, then reduce intervention only after the behavior is understood.

The choice between human and automated participation is not only a safety setting. It changes the information available to the rest of the system and the timing of its transitions. A person may recognize that a formally valid answer misunderstands the real request. An executor may return a precise error quickly but cannot decide whether the requested operation is wise. The LLM may connect both signals to a new proposal, yet may also over-trust a misleading observation. A design that names these differences can decide where to pause and where to automate; a design that hides them inside one agent makes that decision harder to audit.

The pattern also supports extension without redesigning every participant. Developers can reuse a built-in reply method, alter an agent’s instructions or input mode, configure its execution behavior, or add a custom reply function for a specialized situation. The framework’s value here is compositional: a retrieval-capable proxy, a domain-specific executor, or a human expert can be introduced as a participant that still exchanges messages with the existing agents. The new capability becomes useful only when the rest of the conversation knows when to call it and how to interpret what comes back.

That last condition is where many claims about modularity need qualification. A shared interface lowers the cost of connecting components; it does not guarantee that their assumptions match. An assistant may generate code that a tool cannot run. A tool may return an error that the assistant misreads. A person may provide an answer that conflicts with the task’s required format. A customized agent may preserve the same message methods while changing the meaning of its replies. In each case, the interface transmits a response, but the workflow still needs a way to recognize whether the response is usable.

There are also hidden dependencies inside an apparently clean boundary. The meaning of a message can depend on prior context that was not included. An execution result can be uninterpretable without the exact environment in which it was produced. A human request can be triggered too often and turn an automated process into a sequence of interruptions. Conversely, suppressing human input too early can hide failures that would have been obvious during development. AutoGen’s guidance to begin with humans in the loop is therefore practical: it creates a chance to tune prompts, observe corner cases, and learn which transitions really require judgment before asking the system to run unattended.

The practical test is to ask what crosses each boundary and who owns the next decision. The assistant owns a candidate response, not the truth of that response. The executor owns the action it can perform and the observation it returns, not the overall task objective. The human owns the judgment that the workflow explicitly delegates to them, not necessarily every implementation detail. The surrounding conversation must connect these responsibilities while preserving the conditions under which a response counts as progress.

This is why a conversable agent is the smallest useful unit rather than the whole solution. It packages a role, state, capability source, and response behavior in a form that can be composed. Once several such units exist, the central problem shifts: how should receiving one message trigger the next computation, how should the system choose another participant, and where should the conversation stop? Those are questions about programming the interaction itself.

References