An implementation of StrongDM's Attractor—a non-interactive coding agent for use in a software factory—built on StreamWeave.
Attractor is specified by NLSpecs (Natural Language Specs): human-readable specs intended for coding agents to implement and validate behavior. This repository implements that spec using StreamWeave, a composable, async, stream-first Rust framework for building data processing graphs.
- Attractor (strongdm/attractor): Defines the coding agent loop, unified LLM interface, and overall behavior for a software factory agent.
- StreamWeave (Industrial/streamweave): Provides the runtime—graph-based, async stream processing in Rust—used to run the agent loop, tool calls, and I/O.
Together, this project gives you an Attractor-compliant agent implemented in Rust with StreamWeave’s streaming and graph abstractions.
The authoritative Attractor specs live in the upstream repo:
run_dot runs an Attractor pipeline from a .dot file (parse → validate → run):
devenv shell -- cargo run --bin run_dot -- examples/workflows/pre-push.dotOptions (see run_dot --help for full usage): --agent-cmd, --stage-dir (default: .attractor), --run-dir, --resume, --dry-run (validate workflow file only, do not run), --timeout SECS (maximum run time in seconds; on timeout exit with 124). Run state is persisted only via the execution log. Use --run-dir DIR with --execution-log to write DIR/execution.log.json, and --resume DIR to resume from DIR/execution.log.json with the same .dot file. After each run, a summary line is printed: Nodes: N, Success: S, Failed: F, Duration: D.
Environment variables:
ATTRACTOR_AGENT_CMD— Command for agent/codergen nodes (e.g.cursor-agent). When set, agent steps run this with the prompt as stdin; agent runs with stage dir.ATTRACTOR_STAGE_DIR— Directory for staging (default:.attractor).
Example:
devenv shell -- cargo run --bin run_dot -- examples/workflows/pre-push.dotThe main entry point is the simple_pipeline example, which runs a minimal Attractor graph (Run tests → Report). You can run it in several ways:
| Method | Command | Notes |
|---|---|---|
| Nix (remote) | nix run github:Industrial/streamweave-attractor |
Fetches, builds, and runs in one step |
| Nix (local) | nix run |
From a local checkout; builds the example and installs as streamweave-attractor |
| Cargo | cargo run --example simple_pipeline |
Direct run; requires Rust toolchain |
| devenv | devenv shell -- cargo run --example simple_pipeline |
Uses project devenv for consistent tooling |
Examples:
# Run from Nix (no Rust install needed)
nix run github:Industrial/streamweave-attractor
# Run from local checkout with devenv
devenv shell -- cargo run --example simple_pipeline
# Build only
devenv shell -- cargo build --examples- Cargo.lock is committed so that when the repo is used as a flake input (e.g.
github:Industrial/streamweave-attractor), Nix can use it for reproducible builds. Do not addCargo.lockto.gitignore. - The flake depends on streamweave via input
streamweave(default:path:../streamweave). When the flake is consumed from GitHub (e.g. by another project’sdevenv), that path does not exist. Override the input in the consuming flake, for example:streamweave-attractor.url = "github:Industrial/streamweave-attractor"; # Override so the build can find streamweave: streamweave-attractor.inputs.streamweave.url = "github:Industrial/streamweave"; # or path: ./streamweave if you have it in your tree
- cargo2nix is integrated optionally. The default package uses
buildRustPackage. To use cargo2nix (granular Rust builds), generateCargo.nixonce and commit it:Thennix run .#generate git add Cargo.nixnix build .#cargo2nixbuilds the workspace crate via cargo2nix. The defaultnix build/nix runstill usebuildRustPackageand do not requireCargo.nix.
devenv shell -- cargo build
devenv shell -- cargo run --example simple_pipelineRun all quality checks before pushing:
devenv shell -- bin/pre-pushThis runs: format, fix, check, lint, build, test, audit, check-docs. (Examples like simple_pipeline require an LLM—run bin/test-examples manually when needed.) See examples/workflows/pre-push.dot for the bd-centric fix-and-retry workflow.
See CONTRIBUTING.md and AGENTS.md for development workflow and agent instructions.
You can install streamweave-attractor as a CLI in another project’s devenv environment so the streamweave-attractor binary is available in the shell.
In the other project, add streamweave-attractor as an input.
If that project uses a devenv.yaml (standalone devenv), add:
# devenv.yaml
inputs:
streamweave-attractor:
url: github:Industrial/streamweave-attractor
# Optional: use a local checkout instead of GitHub
# streamweave-attractor:
# path: ../streamweave-attractorIf that project uses a Nix flake (e.g. flake.nix with devenv), add the same input to the flake’s inputs and ensure it is passed through to the devenv module (e.g. via inputs in perSystem or your devenv integration).
In the other project’s devenv.nix, add the package so it is on PATH:
{ inputs, pkgs, ... }: {
packages = with pkgs; [
# your other packages ...
inputs.streamweave-attractor.packages.${pkgs.system}.default
];
}After devenv shell (or entering the environment), you can run:
streamweave-attractorThe flake’s default package builds the simple_pipeline example and installs it as the streamweave-attractor binary. For run_dot (DOT-based pipelines), use this repo’s devenv and run:
cargo run --bin run_dot -- examples/workflows/pre-push.dotThis project is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. See LICENSE for details.