chemgraph-loop / src /chemgraph /state /multi_agent_state.py
rockyaaos's picture
ChemGraph Loop: guarded real-agent API (EMT/TBLite single-point energy)
c509967 verified
Raw
History Blame Contribute Delete
2.4 kB
import operator
from typing import TypedDict, Annotated, Any, Literal, Optional
from langgraph.graph import add_messages
def merge_dicts(a: dict, b: dict) -> dict:
"""Reducer that merges dictionaries for executor logs.
Parameters
----------
a : dict
Existing accumulated dictionary.
b : dict
New dictionary update.
Returns
-------
dict
Merged dictionary where values from ``b`` override ``a``.
"""
return {**a, **b}
class ExecutorState(TypedDict):
"""Local state for each executor subgraph spawned via Send().
Each executor instance gets its own isolated copy of this state.
The ``messages`` list holds the executor's ReAct conversation
(system prompt, LLM responses, tool calls/results).
``task_index`` identifies which planner task this executor is
working on, enabling the planner to correlate results with tasks.
``retry_count`` tracks how many times this particular task has
been retried, so the planner and router can enforce retry limits.
"""
messages: Annotated[list, add_messages]
executor_id: str
task_index: int
retry_count: int
class PlannerState(TypedDict):
"""Global state for the main planner-executor graph.
The planner reads ``messages`` (the original user query plus its own
prior outputs) and ``executor_results`` (merged results from all
completed executor subgraphs) to decide what to do next.
``planner_iterations`` tracks how many times the planner has
dispatched tasks to executors, providing a guard against infinite
Planner -> Executor -> Planner cycles.
``failed_tasks`` accumulates structured records of executor
failures across iterations, enabling the planner to make informed
retry decisions. Each entry is a dict with keys: ``task_index``,
``error``, ``retry_count``, and ``executor_id``.
``clarification`` holds the question text when the planner routes
to ``ask_human`` to request human input before proceeding.
"""
messages: Annotated[list, add_messages]
next_step: Literal["executor_subgraph", "ask_human", "FINISH"]
tasks: list[dict[str, Any]]
executor_results: Annotated[list, operator.add]
executor_logs: Annotated[dict[str, list], merge_dicts]
planner_iterations: int
failed_tasks: Annotated[list, operator.add]
clarification: Optional[str]