The core orchestrator in HydraR, AgentDAG defines and executes a
Directed Graph of AgentNode objects. It supports:
Pure DAGs: Parallel execution using
furrr.Cycles & Loops: Iterative execution via conditional edges.
State Isolation: Parallel branch execution in isolated git worktrees.
Persistence: Automatic state checkpointing and restoration.
Public fields
nodesList. Named list of AgentNode objects.
edgesList. Pending edge definitions to be bound.
conditional_edgesList. Conditional transition logic.
error_edgesList. Failover transition logic.
resultsList. Execution results for each node.
trace_logList. Execution telemetry and tracing.
graphigraph. Internal graph representation.
start_nodeString. Explicit entry point for cycles.
stateAgentState. Centralized state object.
message_logMessageLog. Optional audit log.
worktree_managerWorktreeManager. Optional isolation manager.
Methods
Method set_start_node()
Set Start Node(s) Explicitly defines the entry point(s) of the graph. If not called, the engine defaults to nodes with an in-degree of 0. Required for graphs with cycles or where execution must start at a specific node.
Method add_node()
Add a Node
Registers an AgentNode object into the graph.
Method add_edge()
Add an Edge Creates a directed connection between nodes. Also supports specialized edge types (Error, Test, Fail) via labeling.
Arguments
fromString or Character vector. The source node ID(s).
toString. The destination node ID.
labelString. Optional label for the edge. In HydraR, certain labels trigger logic:
"error"or"failover": Creates an error edge."Test": Creates a conditional edge (true path)."Fail": Creates a conditional edge (false path).
Method add_conditional_edge()
Add a Conditional Edge (Loop Support)
Adds branching logic to the graph. After the from node executes,
the test function is evaluated against the node's result.
Method run()
Run the Graph
The primary execution engine for the AgentDAG. It manages the orchestration
lifecycle, including state initialization / recovery, worktree setup for
isolation, and routing between nodes. It automatically switches between
linear (parallel-capable) and iterative execution modes based on the
graph's complexity.
Arguments
initial_stateList, AgentState, or String. The starting data for the workflow. Can be a named list of R objects, an existing
AgentStateinstance, or a path to a checkpoint (if supported). Required unless resuming from a checkpointer.max_stepsInteger. The maximum number of node executions allowed in a single
run()call. Prevents infinite loops in cyclic graphs. Default is 25.checkpointerCheckpointer. An optional
CheckpointerR6 object. If provided, the state is automatically saved after every node execution.thread_idString. A unique identifier for this execution "thread" or session. Required if using a
checkpointerto resolve the correct state from storage.resume_fromString. Optional node ID. If provided (or found in a checkpoint), execution will skip completed nodes and start from this point.
use_worktreesLogical. Enable branch isolation. If
TRUE, parallel branches are executed in separate git worktrees, preventing file-system conflicts between agents.repo_rootString. Path to the master git repository. Required if
use_worktreesisTRUE.cleanup_policyString. One of
"auto"(default),"none", or"aggressive". Determines how worktrees are removed after execution.fail_if_dirtyLogical. If
TRUE, execution fails if therepo_roothas uncommitted changes (recommended for reproducibility when using worktrees).packagesCharacter vector. A list of R packages to load on parallel worker nodes (passed to
furrr)....Additional arguments. Passed down to individual
node$run()calls.
Method .run_linear()
Usage
AgentDAG$.run_linear(
max_steps = 25,
checkpointer = NULL,
thread_id = NULL,
resume_from = NULL,
node_ids = NULL,
step_count = 0,
fail_if_dirty = TRUE
)Method .run_iterative()
Usage
AgentDAG$.run_iterative(
max_steps,
checkpointer = NULL,
thread_id = NULL,
resume_from = NULL,
step_count = 0,
fail_if_dirty = TRUE,
packages = c("withr")
)Method plot()
Generates a visual representation of the DAG using Mermaid or DOT syntax.
Usage
AgentDAG$plot(
type = "mermaid",
status = FALSE,
details = FALSE,
include_params = NULL,
show_edge_labels = TRUE
)Arguments
typeString. Either
"mermaid"(default) for web-native rendering or"grViz"for DiagrammeR/Graphviz.statusLogical. If
TRUE, colors nodes based on the results in the current trace log (Green: Success, Red: Failed, Yellow: Paused).detailsLogical. If
TRUE, injects node parameters into the labels.include_paramsCharacter vector. Optional whitelist of parameter names to display when
detailsisTRUE.show_edge_labelsLogical. Whether to display labels (e.g., "Test", "Fail") on edges.
Method compile()
Rebuilds the internal igraph representation and performs validation
checks such as cycle detection, start node disambiguation, and
reachability analysis. This must be called before run().
Method save_trace()
Exports the detailed telemetry from the last execution (durations, status, outputs) to a JSON file.
Method from_mermaid()
A static-like method to populate a DAG from a Mermaid string using a custom node factory.
Arguments
mermaid_strString. A valid Mermaid graph definition (e.g.,
"graph TD; A-->B").node_factoryFunction. A closure mapping Mermaid labels and parameters to
AgentNodeinstances. Seeauto_node_factoryfor the standard implementation.
Examples
if (FALSE) { # \dontrun{
# 1. Define a complex DAG with branching, loops, and custom state
# Initializing the orchestrator
dag <- AgentDAG$new()
# Define logic for data retrieval and quality control
register_logic("fetcher", function(state) list(status="success", output="raw data"))
register_logic("gate", function(state) {
if (nchar(state$get("fetcher")) > 5) list(status="true") else list(status="false")
})
# 2. Programmatic Node Construction
dag$add_node(AgentLogicNode$new("start", logic_fn = get_logic("fetcher")))
dag$add_node(AgentLogicNode$new("check", logic_fn = get_logic("gate")))
# 3. Connecting nodes with status-based edges
# Errors in 'start' go to a terminal cleanup node
dag$add_edge("start", "check")
dag$add_conditional_edge("check", test = function(res) res$status == "true",
if_true = "process", if_false = "retry")
# 4. Multi-agent execution context
# Compiling and running with initial state
dag$compile()
final_state <- dag$run(initial_state = list(job_id = "123"))
# Checking results
print(final_state$get_all())
} # }
## ------------------------------------------------
## Method `AgentDAG$plot`
## ------------------------------------------------
if (FALSE) { # \dontrun{
dag <- dag_create()
dag$add_node(AgentNode$new("A"))
dag$add_node(AgentNode$new("B"))
dag$add_edge("A", "B", label = "proceed")
# Generate Mermaid string
m_src <- dag$plot(type = "mermaid", show_edge_labels = TRUE)
cat(m_src)
} # }
## ------------------------------------------------
## Method `AgentDAG$from_mermaid`
## ------------------------------------------------
if (FALSE) { # \dontrun{
# Use a custom factory to map all nodes to Logic nodes
simple_factory <- function(id, label, params) {
AgentLogicNode$new(id = id, logic_fn = function(s) list(status="ok"))
}
dag <- AgentDAG$new()
dag$from_mermaid("graph LR; Start-->End", simple_factory)
} # }