SWE-AF

repository·main·Indexed 19 days ago

https://github.com/agent-field/swe-af

An autonomous engineering team runtime built on AgentField (version 0.1.0). It orchestrates a coordinated factory of agents—including product managers, architects, coders, reviewers, and testers—to scope, build, and ship complex software end-to-end via a single API call. The project includes both Python and Go node implementations, with the Go port providing 'swe-planner-go' for full pipelines and 'swe-fast-go' for lightweight operations.

Tokens
45.5K
Snippets
104
Records
188
Agent score
75%

What's inside swe-af

  1. Overview of AgentField Go SDK Packages

    main

    The AgentField Go SDK is organized into several functional packages for building and managing autonomous agents:

    • sdk/go/agent/: The core node runtime. Used for creating agents, registering reasoners/skills, managing the HTTP mux (endpoints like /reasoners/{name}, /execute/{name}, /health), handling async execution, and managing the control-plane lease loop.
    • sdk/go/harness/: A CLI-based coding-agent harness. It provides providers like claude-code, codex, opencode, and gemini. It includes a Runner.Run method that supports structured output via schema files and automatic retries.
    • sdk/go/ai/: A direct LLM API client for chat completions, tool-calling loops, and multimodal capabilities. This is an alternative to the harness.
    • sdk/go/client/: A client for interacting with the control plane, used for executing tasks, DID authentication, and polling for approvals.
    • sdk/go/inputs/: Utilities for manual typed extraction from map[string]any (e.g., RequiredString, Int, Object).
    • sdk/go/types/: Definitions for status enums, discovery, and registration types.
  2. Overview of SWE-AF Go Nodes

    main

    The SWE-AF Go node is a 1:1 Go port of the autonomous engineering node. It registers the same reasoners as the Python node and exposes a byte-compatible HTTP API, allowing the AgentField control-plane DAG UI to render identically.

    There are two primary binaries available in this port:

    1. swe-planner: The full pipeline node (Plan $\rightarrow$ DAG $\rightarrow$ PR). It registers as swe-planner-go and defaults to port 8005.
    2. swe-fast: A lighter-weight fast mode node. It registers as swe-fast-go and defaults to port 8006.

    This Go port is designed to run alongside the Python node. They use distinct identities so both stacks can operate against a single control plane simultaneously.

    | Binary            | Node ID          | Default port |
    |-------------------|------------------|--------------|
    | `swe-planner`     | `swe-planner-go` | `8005`       |
    | `swe-fast`        | `swe-fast-go`    | `8006`       |
  3. Overview of the LLM Rust Python Compiler (Sonnet Run)

    main

    This workspace contains a Rust-based Python compiler generated by SWE-AF. It is designed for production-style Python execution, specifically optimized for high-performance, short Python snippet execution (e.g., for LLM/agent workloads).

    Key features include:

    • High Performance: Achieves significantly higher throughput and lower latency compared to CPython subprocesses (up to 602x faster in steady-state).
    • Safety Controls: Implements module allowlists, timeout paths, and output limits.
    • Typed Results: The Rust API returns structured execution results including stdout, stderr, return, error, and duration.
    • Compact Footprint: The native release binary is approximately 10.79 MiB with a predictable memory footprint (~22.53 MB RSS).
  4. Understand the SWE-AF Go Port Work Breakdown

    main

    The SWE-AF Go Port is organized into a series of sequential and parallel 'Waves' that build the autonomous engineering runtime. The development follows a strict dependency path to ensure core schemas and foundation layers are established before higher-level execution engines and orchestrators are implemented.

    Critical Path for Development: T0 (Scaffold) → T1.1 (Schemas) → T2.2 (Harnessx) → T3.R2 (Roles) → T4.1 (Coding Loop) → T4.2 (DAG) → T5.3 (Build Orchestrator) → T6.2 (Wiring) → T7.1 (Packaging) → T7.2 (Functional Tests).

    Key Waves:

    • Wave 1 & 2: Foundation (Schemas, Runtime, HITL, Config).
    • Wave 4: Execution Engine (Coding Loop and DAG Executor).
    • Wave 5: Orchestrators (Plan, Execute, Build, Resolve, CI-Gate, Approval).
    • Wave 6: Fast Mode and Node Wiring.
    • Wave 7: Packaging and Functional Testing.
  5. Map Python asyncio concurrency to Go concurrency patterns

    main

    When porting the SWE-AF concurrency model from Python to Go, use the following mappings:

    Python PatternGo Implementation
    asyncio.gather(*coros) barriergolang.org/x/sync/errgroup: Use g.Go(...) for tasks and g.Wait() as the barrier.
    Semaphore bounding (max_concurrent_issues)g.SetLimit(n) on the errgroup (preferred) or golang.org/x/sync/semaphore.Weighted.
    _call_with_timeout(coro, timeout)context.WithTimeout(ctx, duration). Thread the resulting ictx into all downstream calls.
    asyncio.create_task(cleanup...) background tasksSpawn go func(){ ... }() and track them with a sync.WaitGroup. Call wg.Wait() before advancing the execution level.
    Cancellation via SDK cancelEvery handler must honor ctx.Done(). Use select { case <-ctx.Done(): ... } in long loops.
    Shared-memory closure (_memory_fn)A coding.Memory struct containing a map[string]any protected by a sync.Mutex.

    Critical Error Handling Note: In Python, gather is often wrapped so exceptions become IssueResult(FAILED_*). In Go, you must mirror this: each g.Go closure must recover/translate its own error into an IssueResult and return nil to the errgroup. This prevents one issue's failure from cancelling all other sibling issues in the same level. Only genuine context cancellation should abort the group.

  6. Implement Human-in-the-Loop (HITL) with hitl core

    main

    The hitl package manages human interaction via the HAX SDK or an internal hitl.Pauser seam.

    HAX Client Integration

    When using the HAX REST API, the client performs a POST to {HAX_SDK_URL}/api/v1/requests with a Bearer HAX_API_KEY and a camelCase JSON body.

    Workflow for RequestUserInputAndPause:

    1. Build the payload (replicating to_payload() from the Python SDK).
    2. Create the request via HAX (POST).
    3. Call client.RequestApproval (sets status to waiting).
    4. Call client.WaitForApproval (polls for completion).
    5. Map the decision to an AskUserResponse status:
      • approved or request_changes $\rightarrow$ submitted
      • rejected $\rightarrow$ cancelled
      • expired $\rightarrow$ timeout

    Modern hitl.Pauser Pattern

    In newer versions, the poll-based approach is replaced by a single agent.Pause(...) call behind a hitl.Pauser seam. This uses a webhook-resumed pattern. The workflow is:

    1. Build payload $\rightarrow$ HAX create $\rightarrow$ pauser.Pause(ApprovalRequestID, ApprovalRequestURL, ExpiresInHours, ExecutionID).
    2. Map to AskUserResponse using the same status table as above.
  7. How agent roles are invoked and visualized in the DAG

    main

    In SWE-AF, every agent role is a separately registered AgentField reasoner using the @router.reasoner() decorator.

    To ensure each role appears as a distinct node in the AgentField execution DAG (Directed Acyclic Graph) UI, orchestrators must invoke roles using the cross-reasoner .call() method on the application instance.

    Invocation Pattern: app.call(f"{NODE_ID}.run_<role_name>", **kwargs)

    This pattern allows the execution engine to track the lifecycle, inputs, and outputs of each specific role as a discrete step in the workflow.

    # Example of how an orchestrator calls a specific role
    await app.call("swe-planner.run_product_manager", task_prompt="...")
  8. How Risk-Proportional Resource Allocation works

    main

    SWE-AF allocates QA resources based on the risk level of a task, determined by the Sprint Planner's IssueGuidance.needs_deeper_qa flag.

    • Default Path (Low Risk): Uses 2 LLM calls (Coder $\rightarrow$ Reviewer). Best for well-scoped, low-risk issues.
    • Flagged Path (High Risk): Uses 4 LLM calls (Coder $\rightarrow$ QA & Reviewer in parallel $\rightarrow$ Synthesizer). Used for complex issues touching interfaces or large scopes. The risk_rationale field in the guidance documents the reason for this allocation.
  9. How Cross-Agent Knowledge Propagation works

    main

    When enable_learning=true, SWE-AF uses a shared memory store to allow agents to learn from the discoveries and mistakes of their predecessors and siblings. This memory is injected into every coding iteration as context.

    Shared Memory Keys:

    Memory KeyWritten WhenRead ByContent
    codebase_conventionsFirst successful coderAll subsequent codersDiscovered conventions (naming, patterns, structure)
    failure_patternsAfter any failureAll subsequent codersLast 10 failure patterns with issue context
    bug_patternsAfter any failureAll subsequent codersLast 20 common bug types with frequency and affected modules
    interfaces/{issue_name}On issue completionDependent issuesExported interfaces, created files, test status
    build_healthContinuouslyOrchestration agentsAggregate status: passing/failing modules, test counts, debt items
  10. PyRust Execution Modes Comparison

    main

    PyRust offers three primary execution modes for production-ready CLI performance, providing significant speedups over CPython 3.x. Choose a mode based on your latency and throughput requirements:

    1. Binary Mode: Executes as a full subprocess. Best for one-off CLI tasks where process isolation is required. Includes full process spawn, execution, and output capture overhead.
    2. Daemon Mode: Uses Unix socket IPC to communicate with a running process. Best for high-frequency requests where you want to amortize the process spawn cost. Latency is dominated by IPC overhead.
    3. Cached Mode: Uses an in-memory LRU cache. Best for repeated code execution. It performs a hash lookup and executes bytecode directly, bypassing compilation.
    4. Library Mode: Direct in-memory calls. Provides the lowest possible latency (nanoseconds) by eliminating all I/O and IPC overhead.
  11. Understand the SWE-AF Build Pipeline

    main

    SWE-AF operates as an swe-planner node on the AgentField control plane. It follows an idempotent, six-phase build pipeline that transforms a natural-language goal into a verified codebase and a draft GitHub PR. Because the pipeline is idempotent, you can use resume_build() to restart from the exact point of failure using checkpoints created at phase boundaries.

    Build Phases:

    1. Plan + Git Init: Concurrent execution of the planning chain (producing PRD, architecture, and Issue DAG) and run_git_init to set up the integration branch.
    2. Execute Issue DAG: Runs issues through hierarchical escalation loops, parallelizing work based on dependency levels. Returns a DAGState.
    3. Verify-Fix Loop: A self-correcting loop where a Verifier agent checks the codebase against PRD acceptance criteria. If verification fails, a Fix Generator produces new issues that are fed back into Phase 2. This loop is bounded by max_verify_fix_cycles + 1.
    4. Repo Finalize: Cleanup of build artifacts and .gitignore updates (non-blocking).
    5. Push + Draft PR: Pushes the branch and creates a PR via gh. The PR includes the PRD, architecture, and technical debt.
    6. Result: Returns a BuildResult containing the plan, DAGState, verification status, and the PR URL.
    flowchart TD
        A["Phase 1: Plan + Git Init<br/><i>(parallel)</i>"] --> B["Phase 2: Execute Issue DAG"]
        B --> C{"Phase 3: Verify"}
        C -- "pass" --> E["Phase 4: Repo Finalize"]
        C -- "fail" --> D["Generate Fix Issues"]
        D --> B
        E --> F["Phase 5: Push + Draft PR"]
        F --> G["BuildResult"]
  12. How Agent Isolation and Semantic Reconciliation work

    main

    To prevent write conflicts and race conditions during parallel execution, SWE-AF employs agent isolation and semantic reconciliation.

    • Isolation: Each parallel issue is assigned its own git worktree on a dedicated branch (issue/{NN}-{slug}). This provides full filesystem access without lock contention or interference.
    • Semantic Reconciliation: Instead of a mechanical git merge, the Merger agent performs a semantic merge. It reads the PRD, architecture context, and file conflict annotations to understand the intent of each change. This allows it to resolve conflicts by preserving the logic of both changes rather than just resolving line-based diffs.