Share what an AutoGen run produced
An assistant agent writes the analysis. A user-proxy agent executes the code
that renders it. Somewhere in coding/ there is now a perfectly good
summary.html, and the transcript ends with a wall of messages that nobody
outside the run will ever read.
The output exists twice — as a file in a work directory and as text in a message list — and neither form is something you can send to a person.
The work_dir is the trap
AutoGen's code executors are deliberately sandboxed. LocalCommandLineCodeExecutor
writes under a work directory; the Docker executor writes inside a container
that is torn down after the run. That is correct behaviour for executing
model-written code, and it means generated files are, by design, not where a
reader can get them.
Register publishing as a tool
Give the last-speaking agent a function and let the chat's termination depend on it:
def publish_report(title: str, html: str) -> str:
"""Publish an HTML report and return its shareable URL."""
r = httpx.post(
"https://commareports.com/api/v1/reports",
headers={"Authorization": f"Bearer {os.environ['COMMA_API_TOKEN']}"},
json={"title": title, "html": html},
)
r.raise_for_status()
return r.json()["url"]
Then make the exit condition the thing you actually want:
Produce the report, call publish_report with it, and reply with the URL
followed by TERMINATE. Do not reply TERMINATE without a URL.
Termination conditions are the leverage point in AutoGen. A group chat that
can only end by producing an address will produce an address; one that ends on
a keyword will end with the document still in coding/.
Multi-agent output needs one owner
Group chats fail at this differently from single agents: five agents each hold a fragment, and the assembled document exists only implicitly, spread across the message list.
Add a reporter agent whose entire job is assembly and publication. It reads the chat, writes one document, publishes once, and returns the link. One report, one address — instead of four partial pastes and an argument about which was final.
The review leg
Once the report has an id, the next run can start from the feedback:
Fetch open comment threads on report
<id>, revise the analysis to address them, update the same report, and reply in each thread.
See letting an agent respond to comments. Anchored comments matter here more than in most workflows, because the disagreement is usually with one claim in one section, not the report — see commenting on HTML.
Worth knowing
- Do not put the HTML in the chat. Pasting a rendered document into the message list costs context on every subsequent turn, for every agent.
reports:writeonly. An agent that also executes model-written code should hold the narrowest token you can give it — see scoped tokens for AI agents.- 5 MB per report body.
- Reports render sandboxed —
allow-scripts, noallow-same-origin.
Try it
Free — unlimited reports, commenters and revisions.