feat(runtime): añade build_graph (StateGraph + routing condicional + interrupt HITL)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Juan
2026-05-10 15:15:35 +02:00
co-authored by Claude Opus 4.7
parent d8c5c23e2a
commit d56624c90e
2 changed files with 200 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
"""Compilación del grafo LangGraph para un AgentDefinition concreto."""
from __future__ import annotations
from typing import Any
from langgraph.checkpoint.base import BaseCheckpointSaver
from langgraph.graph import END, START, StateGraph
from agentforge_core.domain.agent import AgentDefinition
from agentforge_core.domain.policy import PolicyDefinition
from agentforge_core.guardrails.base import GuardrailEngine
from agentforge_core.llm.base import LLMProvider
from agentforge_core.runtime.nodes import (
build_node_approve_gate,
build_node_finalize,
build_node_llm_reason,
build_node_propose_actions,
build_node_validate_input,
build_node_validate_output,
)
from agentforge_core.runtime.state import AgentState
def build_graph(
*,
agent_def: AgentDefinition,
policy: PolicyDefinition,
provider: LLMProvider,
engine: GuardrailEngine,
checkpointer: BaseCheckpointSaver[Any],
) -> Any:
"""Construye y compila el grafo de ejecución del agente."""
g = StateGraph(AgentState)
g.add_node("validate_input", build_node_validate_input(engine, policy))
g.add_node("llm_reason", build_node_llm_reason(provider, agent_def))
g.add_node("validate_output", build_node_validate_output(engine, policy))
g.add_node("propose_actions", build_node_propose_actions())
g.add_node("approve_gate", build_node_approve_gate(agent_def))
g.add_node("finalize", build_node_finalize())
g.add_edge(START, "validate_input")
def _after_validate_input(state: AgentState) -> str:
return END if state.get("status") == "blocked_by_guardrail" else "llm_reason"
g.add_conditional_edges(
"validate_input", _after_validate_input, {END: END, "llm_reason": "llm_reason"}
)
def _after_llm(state: AgentState) -> str:
return END if state.get("status") == "failed" else "validate_output"
g.add_conditional_edges(
"llm_reason", _after_llm, {END: END, "validate_output": "validate_output"}
)
def _after_validate_output(state: AgentState) -> str:
if state.get("status") in {"blocked_by_guardrail", "failed"}:
return END
return "propose_actions"
g.add_conditional_edges(
"validate_output", _after_validate_output, {END: END, "propose_actions": "propose_actions"}
)
g.add_edge("propose_actions", "approve_gate")
g.add_edge("approve_gate", "finalize")
g.add_edge("finalize", END)
return g.compile(checkpointer=checkpointer)