Anyone who has given autonomous AI coding agents (Claude, Devin, Antigravity, or Copilot Workspace) free rein in a production repository knows the uneasy feeling: in one minute, the agent writes a brilliant algorithm; in the next, it touches an unrelated file, rewrites your go.mod, hallucinates non-existent unit tests, and tries to commit directly to main.
The industry is beginning to recognize a fundamental truth:
The real bottleneck in AI-assisted software engineering isn't token speed or code generation. It is the ability to verify, constrain, and deterministically govern what gets generated.
During my postgraduate studies in Applied AI Engineering, I set out to turn this recurring friction into an industrial software engineering standard: Pipeline-AI.
In this article, I will break down how we built a deterministic, zero-trust multi-agent workflow powered by Go 1.24 OS lifecycle hooks, strict TDD, and role specialization integrated natively into the Google Antigravity ecosystem.
The Trap: Why "Prompt Engineering" Fails at Governance
The naive way to control an AI agent is to append natural language constraints to its prompt:
"Please do not modify files outside of
internal/user/, and never commit directly to main."
This fails because of a mathematical reality: LLMs are probabilistic, but software engineering requires deterministic guarantees.
If an LLM has a 1% chance of ignoring an instruction under a dense context window or deep reasoning tree, that 1% will manifest in your release branch. Governance cannot live inside the agent's prompt — it must live in the execution environment (at the operating system level).
1. Zero-Trust Defense: OS Lifecycle Hooks (PreToolUse)
Our first architectural decision was enforcing the principle of least privilege: the main interactive chat session is physically prohibited from editing code directly.
Google Antigravity provides native lifecycle hooks, notably the PreToolUse event. Whenever an agent invokes a file modification tool (write_to_file, replace_file_content), the hook intercepts the request before a single byte is touched on disk.
We built pipeline-hook, a statically compiled Go 1.24 binary with zero external dependencies (stdlib only). It intercepts the JSON payload on stdin, identifies which subagent is executing, and checks the target file against project guardrails:
// Simplified interception logic from pipeline-hook in Go
func run(stdin io.Reader, stdout, stderr io.Writer) int {
var in hookInput
if err := json.Unmarshal(raw, &in); err != nil {
return replyAllow(stdout)
}
// Intercept disk mutation attempts
if editTools[in.ToolName] {
target := in.FilePath()
// Check against protected paths defined in .pipeline-ai.json
if cfg.IsProtected(target) && !cfg.IsEditorAgent(in.AgentType) {
msg := fmt.Sprintf(
"BLOCKED: Agent '%s' is not authorized to edit '%s'. "+
"Only authorized agents [%s] can modify this directory.",
in.AgentType, target, strings.Join(cfg.EditorAgents, ", "),
)
// Emits JSON {"decision": "deny", "reason": "..."} to stdout with exit 0
return replyDeny(msg, stdout)
}
}
return replyAllow(stdout)
}
If a product triage agent or an unauthorized session attempts to modify internal/auth/token.go, the OS hook immediately halts the call with decision: deny. There is no prompting negotiation: the tool call is blocked at the system boundary.
2. The 16-Skill Pipeline: Specialization vs. Monolithic Agents
A common anti-pattern is relying on a "do-it-all" agent. Asking a single prompt to understand business requirements, architect database schemas, write unit tests, implement the code, and review diffs results in massive context drift and shallow reasoning.
In Pipeline-AI, we decomposed the software development lifecycle into 16 specialized skills:
1. pm-triage → Classifies scope, tags DEL-ID, identifies technical requirements
2. architecture-guardrails → Establishes technical boundaries and invariant locks
3. [data-model] → Designs schemas & entities (PostgreSQL, Mongo, DynamoDB)
4. test-writer → Authors table-driven tests and fuzz targets (Red phase)
5. dev-implementation → Implements code strictly until tests pass (Green phase)
6. code-reviewer → Audits diffs separating hard blockers from suggestions
7. [migration-reviewer] → Validates DDL idempotency, locks, and rollback safety
8. [security-review] → Automatically triggered when auth, crypto, or storage is touched
9. [supply-chain-review] → Audits go.mod changes and invokes govulncheck
10. qa-validation → Executes the full test suite and validates project invariants
11. [release-ops] → Handles SemVer, manifests, and deployment readiness
12. docs-update → Compiles the audited delivery report with diff evidence
13. git-delivery → Creates isolated branch, conventional commit, and Pull Request
(Brackets denote optional modules activated via configuration).
Each agent has clear boundaries: the code-reviewer has read-only permissions and cannot edit code; the dev-implementation agent only begins working after test-writer has committed failing tests.
3. Strict TDD as the Antidote to Hallucinations
The single best specification for an LLM is a failing unit test:
-
Red: The
test-writeragent receives the architectural guardrails and writes comprehensive table-driven tests using Go's standardtestingpackage. It runsgo test ./...and proves the failure. -
Green: The
dev-implementationagent takes over. Its job is not to guess user intent or speculate on future features — its sole goal is to make the tests pass. -
Refactor & Format: When
go test -race ./...is green andgofmtformats the code automatically viaPostToolUsehooks, implementation stops. Zero dead code, zero scope creep.
4. The Delivery Gatekeeper: pipeline-validate
Before any Pull Request is created, our custom validator verifies the delivery:
go tool pipeline-validate docs-ai/deliveries/DEL-011/report.md
The validator automatically rejects the delivery if:
- Checklist tasks remain unchecked.
- The delivery report contains unresolved markers (
TODO,FIXME,TBD, filler text). - The real
git difftouches security-sensitive files (security_surface_paths) without an explicitly approved security audit section.
If the gatekeeper fails, Git delivery is aborted. The PR cannot be opened.
5. Real-World Case Study: Desktop Go + SQLite
We validated this pipeline in an active desktop application:
- Zero CGO Invariant: The pipeline enforced that no external dependencies broke cross-compilation from Linux/WSL2 to Windows, producing a standalone 37MB executable.
-
Proactive Security: When an agent modified
internal/storage/sqlite/, the pipeline automatically flagged a security surface touch, enforcing parameterized queries (SQL injection prevention) and passinggovulncheck. -
Git Protection: Direct pushes to
mainwere blocked locally by.githooks/pre-pushand remotely by GitHub Rulesets. All deliverables reached production via clean, squashed PRs.
Key Takeaways for Applied AI Engineers
- Treat AI agents like hyper-fast junior engineers with terminal access: Give them powerful tools, but isolate them with deterministic OS hooks and comprehensive test suites.
-
Determinism beats probability: Whenever possible, replace natural language prompting with compiled CLI gates (
go tool) and static linters. - Role specialization minimizes context degradation: Smaller agents with surgical scopes consume fewer tokens, make fewer mistakes, and are dramatically easier to audit.
Open Source
The complete toolkit — including the pipeline-init scaffolding CLI, Go hooks, and the full catalog of 16 Antigravity skills — is open-source under the MIT license:
👉 GitHub: rodrigodosanjosoliveira/pipeline-ai
How are you handling governance and guardrails for autonomous coding agents in your workflows? Let's discuss in the comments below! 💬👇
Top comments (0)