Agent Harness API Reference¶
A Python package implementing a compositional execution-state management system for long-horizon agentic code generation loops, with full dependency tracking, feedback-driven patch generation, and selective re-execution.
Package: agent_harness
Python Version: 3.8+
Dependencies: networkx, asttokens, astunparse, openai, pydantic, pytest
Module: dependency_analyzer¶
Analyzes code dependencies by extracting variable reads and writes, and inferring data flow edges between execution steps.
get_reads(source: str) -> set[str]¶
Extracts the set of variable names that are read (referenced) in the given source code.
Parameters:
- source (str): Python source code as a string
Returns:
- set[str]: Set of variable names that are read in the code
Example:
from agent_harness.dependency_analyzer import get_reads
code = "result = x + y"
reads = get_reads(code)
print(reads) # {'x', 'y'}
get_writes(source: str) -> set[str]¶
Extracts the set of variable names that are written (assigned) in the given source code.
Parameters:
- source (str): Python source code as a string
Returns:
- set[str]: Set of variable names that are assigned in the code
Example:
from agent_harness.dependency_analyzer import get_writes
code = "result = x + y\noutput = result * 2"
writes = get_writes(code)
print(writes) # {'result', 'output'}
infer_edges(steps: list[tuple[str, str]]) -> list[tuple[str, str]]¶
Infers data flow dependencies between execution steps by analyzing variable reads and writes.
Parameters:
- steps (list[tuple[str, str]]): List of (step_id, source_code) tuples
Returns:
- list[tuple[str, str]]: List of (src_step_id, dst_step_id) edges representing data dependencies
Example:
from agent_harness.dependency_analyzer import infer_edges
steps = [
("step1", "x = 10"),
("step2", "y = x + 5"),
("step3", "z = y * 2")
]
edges = infer_edges(steps)
print(edges) # [('step1', 'step2'), ('step2', 'step3')]
Module: esg¶
Manages the Execution State Graph (ESG), a directed acyclic graph representing the execution history, dependencies, and status of code steps.
class StepStatus(enum.Enum)¶
Enumeration representing the execution status of a step.
Members:
- PENDING: Step has not been executed
- EXECUTING: Step is currently executing
- SUCCESS: Step executed successfully
- FAILED: Step execution failed
- STALE: Step output is invalidated due to upstream changes
Example:
from agent_harness.esg import StepStatus
status = StepStatus.SUCCESS
print(status.name) # 'SUCCESS'
print(status.value) # 'success'
class ExecutionStateGraph¶
Manages the execution state graph with methods for adding steps, tracking dependencies, and managing re-execution.
graph(self) -> nx.DiGraph¶
Returns the underlying NetworkX directed graph representation of the execution state.
Returns:
- nx.DiGraph: NetworkX directed graph object
Example:
from agent_harness.esg import ExecutionStateGraph
esg = ExecutionStateGraph()
esg.add_step("step1", "x = 10")
nx_graph = esg.graph()
print(nx_graph.nodes())
add_step(self, step_id: str, source: str) -> str¶
Adds a new execution step to the graph with the provided source code.
Parameters:
- step_id (str): Unique identifier for the step
- source (str): Python source code for the step
Returns:
- str: The step_id that was added
Example:
from agent_harness.esg import ExecutionStateGraph
esg = ExecutionStateGraph()
step_id = esg.add_step("step1", "x = 10")
print(step_id) # 'step1'
get_node(self, step_id: str) -> dict[str, Any]¶
Retrieves metadata and state information for a specific step node.
Parameters:
- step_id (str): Identifier of the step
Returns:
- dict[str, Any]: Dictionary containing node attributes (source, status, output, etc.)
Example:
from agent_harness.esg import ExecutionStateGraph
esg = ExecutionStateGraph()
esg.add_step("step1", "x = 10")
node = esg.get_node("step1")
print(node['source']) # 'x = 10'
add_edge(self, src_step_id: str, dst_step_id: str) -> None¶
Adds a directed edge representing a data dependency from source step to destination step.
Parameters:
- src_step_id (str): Source step identifier
- dst_step_id (str): Destination step identifier
Returns:
- None
Example:
from agent_harness.esg import ExecutionStateGraph
esg = ExecutionStateGraph()
esg.add_step("step1", "x = 10")
esg.add_step("step2", "y = x + 5")
esg.add_edge("step1", "step2")
record_output(self, step_id: str, output: dict[str, Any], status: StepStatus) -> None¶
Records the execution output and status for a completed step.
Parameters:
- step_id (str): Identifier of the step
- output (dict[str, Any]): Dictionary of variable names to output values
- status (StepStatus): Execution status of the step
Returns:
- None
Example:
from agent_harness.esg import ExecutionStateGraph, StepStatus
esg = ExecutionStateGraph()
esg.add_step("step1", "x = 10")
esg.record_output("step1", {"x": 10}, StepStatus.SUCCESS)
get_ancestors(self, step_id: str, variable_names: set[str] | None = None) -> list[str]¶
Retrieves all ancestor steps that contribute to the specified step's inputs, optionally filtered by variable names.
Parameters:
- step_id (str): Identifier of the step
- variable_names (set[str] | None): Optional set of variable names to filter ancestors by. If None, all ancestors are returned.
Returns:
- list[str]: List of ancestor step identifiers
Example:
from agent_harness.esg import ExecutionStateGraph
esg = ExecutionStateGraph()
esg.add_step("step1", "x = 10")
esg.add_step("step2", "y = x + 5")
esg.add_step("step3", "z = y * 2")
esg.add_edge("step1", "step2")
esg.add_edge("step2", "step3")
ancestors = esg.get_ancestors("step3")
print(ancestors) # ['step1', 'step2']
ancestors_filtered = esg.get_ancestors("step3", variable_names={"y"})
print(ancestors_filtered) # ['step2']
get_subgraph_from(self, step_id: str) -> list[str]¶
Retrieves all descendant steps that depend (directly or indirectly)