Loading...
Loading...
Compare original and translation side by side
from typing import TypedDict, Annotated
from operator import add
class WorkflowState(TypedDict):
input: str
output: str
agent_responses: Annotated[list[dict], add] # Accumulates
metadata: dictfrom typing import TypedDict, Annotated
from operator import add
class WorkflowState(TypedDict):
input: str
output: str
agent_responses: Annotated[list[dict], add] # Accumulates
metadata: dictfrom langgraph.graph import MessagesState
from langgraph.graph.message import add_messages
from typing import Annotatedfrom langgraph.graph import MessagesState
from langgraph.graph.message import add_messages
from typing import Annotated
**Why `add_messages` matters:**
- Appends new messages (doesn't overwrite)
- Updates existing messages by ID
- Handles message deduplication automatically
> **Note**: `MessageGraph` is deprecated in LangGraph v1.0.0. Use `StateGraph` with a `messages` key instead.
**`add_messages`的重要性:**
- 追加新消息(不会覆盖原有内容)
- 根据ID更新现有消息
- 自动处理消息去重
> **注意**:`MessageGraph`在LangGraph v1.0.0中已被弃用,请改用带有`messages`键的`StateGraph`。from pydantic import BaseModel, Field
class WorkflowState(BaseModel):
input: str = Field(description="User input")
output: str = ""
agent_responses: list[dict] = Field(default_factory=list)
def add_response(self, agent: str, result: str):
self.agent_responses.append({"agent": agent, "result": result})from pydantic import BaseModel, Field
class WorkflowState(BaseModel):
input: str = Field(description="User input")
output: str = ""
agent_responses: list[dict] = Field(default_factory=list)
def add_response(self, agent: str, result: str):
self.agent_responses.append({"agent": agent, "result": result})from typing import Annotated
from operator import add
class AnalysisState(TypedDict):
url: str
raw_content: str
# Accumulate agent outputs
findings: Annotated[list[Finding], add]
embeddings: Annotated[list[Embedding], add]
# Control flow
current_agent: str
agents_completed: list[str]
quality_passed: boolAnnotated[list[T], add]addaddfrom typing import Annotated
from operator import add
class AnalysisState(TypedDict):
url: str
raw_content: str
# Accumulate agent outputs
findings: Annotated[list[Finding], add]
embeddings: Annotated[list[Embedding], add]
# Control flow
current_agent: str
agents_completed: list[str]
quality_passed: boolAnnotated[list[T], add]addaddfrom typing import Annotated
def merge_dicts(a: dict, b: dict) -> dict:
"""Custom reducer that merges dictionaries."""
return {**a, **b}
class State(TypedDict):
config: Annotated[dict, merge_dicts] # Merges updates
def last_value(a, b):
"""Keep only the latest value."""
return b
class State(TypedDict):
status: Annotated[str, last_value] # Overwritesfrom typing import Annotated
def merge_dicts(a: dict, b: dict) -> dict:
"""Custom reducer that merges dictionaries."""
return {**a, **b}
class State(TypedDict):
config: Annotated[dict, merge_dicts] # Merges updates
def last_value(a, b):
"""Keep only the latest value."""
return b
class State(TypedDict):
status: Annotated[str, last_value] # Overwritesdef node(state: WorkflowState) -> WorkflowState:
"""Return new state, don't mutate in place."""
# Wrong: state["output"] = "result"
# Right:
return {
**state,
"output": "result"
}def node(state: WorkflowState) -> WorkflowState:
"""Return new state, don't mutate in place."""
# Wrong: state["output"] = "result"
# Right:
return {
**state,
"output": "result"
}from dataclasses import dataclass
from langgraph.graph import StateGraph
@dataclass
class ContextSchema:
"""Runtime configuration, not persisted in state."""
llm_provider: str = "anthropic"
temperature: float = 0.7
max_retries: int = 3
debug_mode: bool = Falsefrom dataclasses import dataclass
from langgraph.graph import StateGraph
@dataclass
class ContextSchema:
"""Runtime configuration, not persisted in state."""
llm_provider: str = "anthropic"
temperature: float = 0.7
max_retries: int = 3
debug_mode: bool = Falseif context.debug_mode:
logger.debug(f"Response: {response}")
return {"output": response}if context.debug_mode:
logger.debug(f"Response: {response}")
return {"output": response}undefinedundefinedfrom langgraph.cache.memory import InMemoryCache
from langgraph.types import CachePolicyfrom langgraph.cache.memory import InMemoryCache
from langgraph.types import CachePolicyundefinedundefinedfrom langgraph.types import RemainingSteps
def agent_node(state: WorkflowState, remaining: RemainingSteps):
"""Proactively handle recursion limit."""
if remaining.steps < 5:
# Running low on steps, wrap up
return {
"action": "summarize_and_exit",
"reason": f"Only {remaining.steps} steps remaining"
}
# Continue normal processing
return {"action": "continue"}from langgraph.types import RemainingSteps
def agent_node(state: WorkflowState, remaining: RemainingSteps):
"""Proactively handle recursion limit."""
if remaining.steps < 5:
# Running low on steps, wrap up
return {
"action": "summarize_and_exit",
"reason": f"Only {remaining.steps} steps remaining"
}
# Continue normal processing
return {"action": "continue"}| Decision | Recommendation |
|---|---|
| TypedDict vs Pydantic | TypedDict for internal state, Pydantic at boundaries |
| Messages state | Use |
| Accumulators | Always use |
| Nesting | Keep state flat (easier debugging) |
| Immutability | Return new state, don't mutate |
| Runtime config | Use |
| Expensive ops | Use |
| Recursion | Use |
| 决策 | 推荐方案 |
|---|---|
| TypedDict vs Pydantic | 内部状态使用TypedDict,边界处使用Pydantic |
| 消息状态 | 使用 |
| 累加器 | 多Agent场景下始终使用 |
| 嵌套 | 保持状态扁平化(便于调试) |
| 不可变性 | 返回新状态,不要原地修改 |
| 运行时配置 | 使用 |
| 高开销操作 | 使用 |
| 递归 | 使用 |
addaddlanggraph-routinglanggraph-checkpointslanggraph-parallellanggraph-supervisorlanggraph-functionaltype-safety-validationlanggraph-routinglanggraph-checkpointslanggraph-parallellanggraph-supervisorlanggraph-functionaltype-safety-validation