Attractor: StrongDM's Radical Bet on Shipping Specifications Instead of Code
Hook
What if the future of open source isn't sharing code at all, but sharing specifications that AI agents compile into code on your machine?
Context
Every software team building with AI eventually hits the same wall: they need their coding agents to run non-interactively in CI/CD pipelines, generate code at scale, and integrate into automated workflows. But tools like Claude, Cursor, and GitHub Copilot are built for interactive development sessions with a human in the loop. When you try to use them in a software factory—generating migrations, scaffolding microservices, or auto-fixing security issues—you're forced to either hack together brittle integrations or surrender control to black-box commercial platforms.
StrongDM, known for their infrastructure access platform, took a different approach with Attractor. Instead of building another coding agent framework with implementation code that would quickly become outdated, they're distributing natural language specifications (NLSpecs) that describe how to build one. It's a meta-project: specifications for creating a non-interactive coding agent, an agentic loop for autonomous operation, and a unified LLM client. You feed these specs to your existing AI coding assistant, which generates the actual implementation. This inverts the traditional open-source model—instead of distributing frozen snapshots of code, you're distributing living blueprints that compile differently based on your environment, your chosen LLM, and even the current date.
Technical Insight
The core architecture revolves around three NLSpec documents that describe distinct components. First, the Attractor agent specification defines a non-interactive coding agent that can receive tasks, plan implementations, generate code, and validate outputs without human intervention. Second, the agentic loop spec describes the orchestration layer—how to queue tasks, manage state, handle failures, and coordinate multiple generation cycles. Third, the unified LLM client spec provides an abstraction over different LLM providers (OpenAI, Anthropic, local models) with consistent interfaces for completion, streaming, and token management.
The implementation pattern is deliberately self-referential. You start by opening the NLSpec files in a coding agent like Cursor or Claude. Here's the workflow:
# Clone the specifications
git clone https://github.com/strongdm/attractor.git
cd attractor
# Open in your coding agent of choice
cursor .
# Prompt your agent with something like:
# "Implement the Attractor coding agent according to the NLSpec,
# targeting Python 3.11 with async/await patterns"
What emerges is code tailored to your stack. If you're a Go shop, your agent generates Go. If you need TypeScript for serverless functions, you get TypeScript. The specifications are language-agnostic by design, describing behavior and interfaces rather than implementation details. This means the same NLSpec can yield a FastAPI-based service, a CLI tool, or a library—whatever fits your architecture.
The non-interactive requirement is crucial for software factory use cases. Traditional coding assistants wait for user approval before applying changes. Attractor-generated agents must make autonomous decisions:
# Example of what an Attractor-generated agent might produce
class AttractorAgent:
def __init__(self, llm_client, validator):
self.llm = llm_client
self.validator = validator
self.autonomous_mode = True
async def execute_task(self, task_spec: TaskSpec) -> Result:
# No human confirmation - full autonomy
plan = await self.llm.generate_plan(task_spec)
for step in plan.steps:
code = await self.llm.generate_code(step)
# Self-validation without human review
if not await self.validator.check(code, step.requirements):
code = await self.llm.refine_code(code, self.validator.errors)
await self.apply_changes(code)
return Result(success=True, artifacts=self.collect_artifacts())
The unified LLM client spec is particularly interesting because it enforces provider-agnostic design. Your generated implementation can swap between Claude, GPT-4, or local models without changing upstream code. This is critical when you're running at scale and need to optimize for cost, latency, or model-specific capabilities. The spec describes interfaces for streaming responses, handling rate limits, and managing context windows—all the operational concerns that differ across providers.
What makes this approach powerful is version control for behavior. When OpenAI releases GPT-5 or Anthropic ships Claude 4, you don't update Attractor's code—you re-run the generation with the new model. The specifications stay stable, but the implementation evolves. If a generated version has bugs, you can regenerate with different prompts, different models, or different temperature settings until you get production-quality code. The NLSpec becomes the source of truth, not the generated artifacts.
Gotcha
The most obvious limitation is that you're not getting battle-tested code. Traditional open source gives you implementation that thousands of developers have run, debugged, and hardened in production. With Attractor, you're getting freshly generated code every time, and its quality depends entirely on which coding agent you use and how well you prompt it. Two developers following the same NLSpec might get implementations with completely different architectures, error handling strategies, or performance characteristics. There's no guarantee of correctness, no test suite proving it works, and no community debugging edge cases.
Reproducibility is another serious concern. If you generate an implementation in January 2024 and your colleague generates one in June 2024 using a newer model version, you might have incompatible codebases even though you started from identical specifications. This breaks fundamental assumptions about how dependencies work. With traditional packages, pinning to version 1.2.3 means everyone gets identical code. With NLSpec-based distribution, there's no such guarantee. You'd need to version-control your generated implementations and treat them as forked code you maintain yourself, which eliminates some of the elegance of the approach. The non-interactive nature also means you're trusting AI to make architectural decisions without oversight—fine for scaffolding, risky for security-critical components.
Verdict
Use if: You're building industrial-scale code generation systems and need full control over your AI infrastructure without depending on commercial platforms. This is ideal for platform teams at mid-to-large companies who already have sophisticated AI tooling, want to customize every aspect of their agentic loops, and have the engineering capacity to validate and maintain generated code. It's also perfect if you're exploring the frontier of spec-driven development and want to experiment with treating natural language as a compilation target. Skip if: You need production-ready code today, lack the expertise to audit AI-generated implementations, or are building anything security-critical without extensive review processes. Also skip if you're a solo developer or small team—the overhead of generating, validating, and maintaining your own implementation outweighs the benefits compared to using a commercial coding agent directly. Traditional open-source libraries with real code are still the safer choice for most use cases.