Task Manager#
BaseTaskManager#
BaseTaskManager is the main integration point in EAA. It owns:
the model object
the registered tools
long-term memory
SQLite persistence
graph compilation and execution
active transcript state
Construction options that matter most in practice are:
llm_configmemory_configtoolsskill_dirscheckpoint_db_pathuse_webuiuse_coding_toolsrun_codes_in_sandboxprune_checkpoints
Built-in graphs#
Chat graph#
build_chat_graph() creates the reusable conversation graph. It:
accepts bootstrap input or waits for user input
calls the model
executes any tool calls
returns to user input when the assistant produces a plain response
This is what backs run_conversation() and
run_conversation_from_checkpoint().
Customization#
Custom graph#
build_task_graph() is the hook for a task-manager-specific LangGraph
workflow. The base class returns None; if you want a custom graph, override
it and implement run() or run_from_checkpoint() around it.
from langgraph.graph import END, START, StateGraph
from eaa_core.task_manager.base import BaseTaskManager
from eaa_core.task_manager.state import TaskManagerState
class CustomState(TaskManagerState):
pass
class CustomTaskManager(BaseTaskManager):
def build_task_graph(self, checkpointer=None):
builder = StateGraph(CustomState)
builder.add_node("call_model", self.node_factory.call_model, input_schema=CustomState)
builder.add_edge(START, "call_model")
builder.add_edge("call_model", END)
return builder.compile(checkpointer=checkpointer)
def run(self):
initial_state = CustomState(
messages=list(self.context),
full_history=list(self.full_history),
)
graph = self.task_graph
graph_kwargs = {}
if self.checkpoint_db_path is not None:
graph, checkpoint_config, _ = self.get_checkpointed_graph(
"task_graph",
load_state=False,
)
self.task_graph = graph
graph_kwargs["config"] = checkpoint_config
final_state = graph.invoke(initial_state, **graph_kwargs)
self.set_active_state(CustomState.model_validate(final_state), "task_graph")
- Status note:
The repository currently does not ship built-in task-manager subclasses that define their own
task_graph. The custom graph hook is present for extension work.
Custom workflow without a graph#
Several analytical task managers in the repository do not rely on a custom LangGraph workflow. Instead, they orchestrate the experiment directly in Python and keep the agent-owned transcript updated through task-manager helpers.
The relevant helpers are:
record_system_message()for narrative progress updatesupdate_message_history()for explicit transcript mutationsadd_webui_message_to_db()for display-only transcript messagesrun_conversation()if control should fall back to free-form chat after the analytical workflow finishes
This pattern is used heavily in
AnalyticalScanningMicroscopeFocusingTaskManager: the code performs explicit
steps, emits status messages as it goes, and can still enter chat mode at the
end.
Checkpointing and resume#
Checkpointing uses the same SQLite database referenced by checkpoint_db_path by
default. The run_*_from_checkpoint() methods also accept a
checkpoint_db_path override when you need to resume from a different SQLite
file. The checkpoint database stores LangGraph checkpoints.
WebUI display messages live in transcript_db_path. Browser input and status
live in the task-manager-owned runtime controller.
The base task manager exposes two resume paths:
run_conversation_from_checkpoint()run_from_checkpoint()for managers that implementtask_graph
Important details:
prune_checkpoints=Truekeeps only the newest checkpoint per graph threadchat and task graph each get their own checkpoint thread id
the WebUI reads transcript messages from
transcript_db_paththrough the agent runtime API