Skip to content

AutoGen

Verified 2026-08-19 — PASS, 5s. Session persistence: save_state() / load_state() blob.

AutoGen serialises the agent’s whole conversation state, so resume keeps structured turns rather than replayed text.


import sys, os, json, asyncio, pathlib
sys.path.insert(0, os.path.expanduser("~/agenttests"))
import azcfg, hetool
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
STATE_DIR = pathlib.Path(os.path.expanduser("~/agenttests/autogen/state"))
STATE_DIR.mkdir(parents=True, exist_ok=True)
def get_working_folder() -> str:
"""Return the agent's current working folder (absolute path)."""
return hetool.get_working_folder()
def run_shell(command: str) -> str:
"""Run a shell command in the working folder and return its output."""
return hetool.run_shell(command)
async def invoke(sid, message):
c = azcfg.load()
model_client = OpenAIChatCompletionClient(
model=c["model"], base_url=c["base_url"], api_key=c["api_key"],
model_info={"vision": False, "function_calling": True, "json_output": True,
"family": "unknown", "structured_output": True},
)
agent = AssistantAgent("assistant", model_client=model_client,
system_message="Be concise. Use tools for operational questions.",
tools=[get_working_folder, run_shell],
reflect_on_tool_use=True)
f = STATE_DIR / f"{sid}.json"
if f.exists():
await agent.load_state(json.loads(f.read_text()))
result = await agent.run(task=message)
reply = result.messages[-1].content.strip()
f.write_text(json.dumps(await agent.save_state()))
await model_client.close()
return reply

Async — the adapter drives the coroutine, so invoke may be async def.


Same shape as every other framework; only file and the runner path change.

{
"type": "process",
"file": "/home/you/autogen/.venv/bin/python3",
"nativeSession": true,
"argsNew": ["/home/you/he_adapter.py", "/home/you/autogen_session.py", "", "{message}"],
"argsResume": ["/home/you/he_adapter.py", "/home/you/autogen_session.py", "{sessionId}", "{message}"],
"replyField": "result",
"sessionIdField": "session_id",
"approve": false,
"workdir": "/home/you/work",
"proxy": { "shape": "openai", "baseUrlEnv": "OPENAI_BASE_URL", "keyEnv": "OPENAI_API_KEY",
"modelEnv": "OPENAI_MODEL", "model": "<route>|<provider model>" }
}

  1. Keep your AssistantAgent and tools as they are.
  2. Wrap agent.run(...) in async def invoke(sid, message).
  3. Add load_state / save_state keyed on sid.
  4. Build OpenAIChatCompletionClient from azcfg.load().
  5. Seal the engine, point external.engine at it, restart.

model_info is required for any non-OpenAI model. The client cannot infer capabilities for an unknown model id and will refuse to start without it. function_calling: True is the field that matters if you bind tools.

reflect_on_tool_use=True or you get the raw tool output. Without it the agent’s last message is the tool result, not a composed answer — so result.messages[-1].content is JSON rather than prose.

Close the client. await model_client.close() before returning, or the process can hang with the connection pool open — which surfaces as a turn that never completes.

Plain callables are fine as tools. No decorator needed; AutoGen introspects the signature and docstring, so write a real docstring — it becomes the tool description the model sees.