From One Sentence to Live Deploy in 2:44 — Watching the Safe-Teams Pipeline Ship a Real Change

From One Sentence to Live Deploy in 2:44

I dropped a single sentence into a Petri-net inbox at 15:48:56 UTC. By 15:51:40, a lime-green banner with the exact text I asked for was rendering on a public production site. No human touched a keyboard between those two moments.

This is what Safe-Teams — an AgenticNetOS net that models a full SAFe agile team as five cooperating sub-nets — actually does in production. Not a demo, not a sandbox: a real Angular app, a real git repository, a real container redeploy, a real public URL. The story below is the receipts, including the part where the QA agent rejected the first attempt and the rework loop turned a bug-flag into a polish improvement.

One sentence in → live page out, in 2 minutes 44 seconds15:48:56prompt“Add a lime-greenbanner to the topof the dashboard.”Architecttier=highdeepseek-671b1 taskDevelopertier=mediumqwen3.5:cloudClaude Code15:50:54commit 596d5b0pushed to main1 line in app.component.ts15:51:39deploy completecontainer restartedHEAD=596d5b015:51:40 — rendered, live, publicSAFE-TEAMS LIVE 2026-05-12T15:48Zvisible at gitanalytics.agentic-nets.com

Five timestamps, three LLM tiers, one running container restart, zero human keystrokes.


The Setup: Five Roles, Five Nets, One Bare Repo

Safe-Teams isn’t one big agent that does everything. It’s five small sub-nets, each modelling a single role from a SAFe agile team. The PM is the only one that talks to the user. The rest run silently behind a shared inbox — just like a real team. The Developer’s actual code edits happen inside a workspace volume, and when the work is done the agent pushes to a bare git repo. A post-receive hook then triggers an auto-deploy daemon. Nothing in this chain talks directly to Docker or Kubernetes. The git push is the deploy.

Safe-Teams Architecture: five role-nets + git as the deploy busFive role-nets (one transition per box)PMt-pm-intake · mediumuser-facingArchitectt-arch-decompose · highDevelopert-dev-plan + claude code · mediumQAt-qa-validate · mediumDevOpst-devops-plan · mediumShared infrastructureWorkspace volume/workspace/git-analytics/Claude Code edits in hereBare git repo/repos/git-analytics.gitpost-receive hook on mainDeploy daemonbuild · push · compose uplistens on :9999Live containernginx + apache reverse proxygitanalytics.agentic-nets.comRole → infra interactionPM creates story token in p-stories(no infra touch — pure planning)Architect emits 1..N task tokens(targets git-analytics-client, files cited)Developer runs Claude Code in workspaceedit + commit + git push origin mainQA reads dev stdout, extracts commit SHAverdict: pass | fail | errorDevOps plans build cmd (validation only)the actual deploy is git push → hookThe orange arrows are the “no-CI/CD” magic: git push → hook → daemon → live.

The orange arrows are the most interesting part. There is no Jenkins, no GitHub Actions, no GitOps controller in this loop — just a 12-line shell script glued to git’s post-receive hook, a tiny HTTP daemon that knows how to docker compose up -d, and a public nginx fronted by Apache. The git push is the deploy.


The Tier System: Why the LLM Bill Doesn’t Blow Up

Earlier this week I added per-transition LLM tier selection to AgenticNetOS. Every agent transition can now declare "tier": "low" | "medium" | "high" in its inscription. The provider-specific model env-vars (OLLAMA_HIGH_MODEL, OLLAMA_MEDIUM_MODEL, OLLAMA_LOW_MODEL) wire those tier names to concrete models. In this run:

TierModelUsed byWhy
lowgemini-3-flash-preview:cloudops watchers, scrum-blocker-sweep, daily-train-statusMechanical scans, heartbeat work
mediumqwen3.5:cloudPM intake, Developer, QA, DevOpsReal work, but pattern-driven
highdeepseek-v3.1:671b-cloudArchitect, PI planning, knowledge-graph synthesisGenuine architectural reasoning
Tier resolution: from inscription label to concrete model nameInscription JSON{ “kind”: “agent”, “action”: { “tier”: “high” }}LlmTierResolvertools → mediumthinking → highdefault = highProvider env-varsOLLAMA_LOW_MODEL= gemini-3-flash-preview:cloudOLLAMA_MEDIUM_MODEL= qwen3.5:cloudOLLAMA_HIGH_MODEL= deepseek-v3.1:671b-cloudEach agent transition picks its own tier; only one of them spends real reasoning quota per story.

The economic shape this gives you is unusual. For one story, the high-tier model fires once (the Architect, on decomposition). The medium-tier model fires four to six times (PM, Dev, QA, DevOps, plus any rework). The low-tier model handles every scheduled scan that runs all day. The expensive thinking happens only when there’s actual ambiguity to resolve.


The Story, Timestamped

Here is the actual prompt I dropped into p-pm-inbox at 15:48:56 UTC. No formatting tricks, no special structure — it’s just plain English a colleague would write:

curl -X POST "http://master:8082/api/runtime/places/p-pm-inbox/tokens?modelId=safe-teams" \
  -d '{
    "name":"verify-live",
    "data":{
      "text":"Add a visible LIVE BADGE at the very top of every page of the
        git-analytics dashboard. The badge must be a lime-green bar with bold
        black text saying EXACTLY: SAFE-TEAMS LIVE 2026-05-12T15:48Z.
        Target service: git-analytics-client. Keep the change minimal."
    }
  }'

And here is what happened next, straight from the master log file:

Story timeline — 2 minutes 44 seconds, end to end15:48:56Token lands in p-pm-inboxone user-written sentence15:49:41Architect fires (tier=high)deepseek-671b decomposes into 1 task, picks files15:50:17Developer plans (tier=medium)qwen3.5 emits a Claude-Code command token15:50:54Commit 596d5b0 pushed+1 line in app.component.ts · executor returned in 13.9s15:50:55post-receive hook firesgit server POSTs to ga-deploy-daemon:9999/deploy15:50:56docker build startscached layers, only Step 5 (COPY .) invalidates15:51:39deploy complete — HEAD=596d5b0container restarted, health check passed15:51:40Banner rendered in browserscreenshot taken · text matches verbatimTotal elapsed2m 44sprompt → live page

The single line of code the Developer agent actually committed:

@@ -8,6 +8,7 @@ import { ThemeService } from './services/theme.service';
   imports: [RouterOutlet],
   template: `
     <div class="wrap" style="display:flex; flex-direction:column; min-height:100vh; min-height:100dvh;">
+      <div style="background:#aaff00; color:#000; font-weight:bold; text-align:center; padding:4px 0; width:100%; flex-shrink:0;">SAFE-TEAMS LIVE 2026-05-12T15:48Z</div>
       <div style="flex:1; min-height:0; width:100%; position:relative;">
         <router-outlet />
       </div>

That’s it. One line, exactly placed, with the correct hex code, semantic markup, and inline styles that don’t conflict with the surrounding flex container. The Developer agent didn’t edit the CSS file (which the Architect had suggested); it edited app.component.ts inline template because that’s where the parent .wrap div lives. Real judgment, made by a medium-tier model with a tight Claude-Code prompt.


The Plot Twist: QA Rejected It

The interesting part of this run isn’t the happy path. It’s what happened after the Developer succeeded but didn’t echo the commit SHA in its stdout. The QA agent looked at the dev’s summary, ran its commit-SHA regex against the text, found nothing usable, and routed the token to p-qa-fail with reason="ambiguous".

This is the safe-teams design at work: never let a deploy through on faith. If you can’t prove a commit happened, you fail closed. The rework loop kicked in and routed a new story back to the Developer with the diagnostic attached. Here’s the part that surprised me:

The rework loop produced a polish, not a duplicate596d5b0 · 15:50:54Add live badge componentpadding:4px 0 · no box-sizingQA: “no SHA in stdout → fail”rework with diagnosticbebc9da · 15:53:56Fix badge padding + box-sizingpadding:4px 8px · box-sizing:border-boxReal polish, not duplicationWhat the medium-tier dev agent did on rework• Read the file. Saw the badge from commit 596d5b0 already there.• Did NOT add a second badge.• Noticed padding:4px 0 + width:100% can overflow on narrow viewports.• Added padding:4px 8px for horizontal breathing room AND box-sizing:border-box to keep the 100% width safe.

The rework cycle produced a real engineering improvement. Confronted with a file that already contained the change, the Developer agent inspected the existing markup, identified a layout subtlety (horizontal padding combined with 100% width without box-sizing overflows the parent container), and shipped a one-character-different version that polishes it.

This is not how Stack-Overflow-stitching coding assistants behave. This is what happens when a small, focused model has just enough context (the inscription tells it: read the file, look at QA’s reason, make the smallest change that satisfies QA) and no extraneous responsibility.


Why git push Is The Whole Pipeline

Every CI/CD system I’ve worked with operates on the same shape: trigger → runner → build → artifact → deploy. Adding an LLM agent on top usually means strapping it onto step 1 (the trigger) and praying the rest still works. Safe-Teams inverts this:

  • The agent is the trigger. A successful Developer fire ends with git push origin main. Nothing more.
  • The hook is the orchestrator. A 12-line shell script on the git server posts to a daemon. That’s the entire glue.
  • The daemon is the deployer. Single binary, listens on a port, runs docker compose up -d. No YAML pipeline file.
  • QA happens after the fact. The page is already live by the time QA finishes deciding whether to pass or rework. If something is wrong, the next commit fixes it — same path, no rollback needed.

You could argue this is irresponsible. I’d argue it’s honest. The deploy was never going to wait for QA in a system that ships every push to main; pretending otherwise just adds latency. What safe-teams adds is a second-pass quality gate that can rework an already-deployed change in the same flow — and that second pass is good enough to catch real issues, as the rework story above shows.


Real Numbers from This Run

MetricValueNote
Prompt to live page2m 44sp-pm-inbox at 15:48:56 → banner rendered at 15:51:40
Architect reasoning time~8sdeepseek-671b, one CREATE_TOKEN
Developer plan time~25sqwen3.5, computes workingDir + Claude-Code prompt
Claude-Code edit + commit + push13.9sOne file changed, one line added
Container rebuild + restart~45sMost layers cached, only Angular re-bundle changed
High-tier LLM fires per story1Architect only
Medium-tier LLM fires per story4–6PM, Dev, QA, DevOps, plus any rework
Files changed1git-analytics-client/src/app/app.component.ts
Diff size+1 lineOriginal commit. Polish commit was a 1-attribute change.

Where This Leads

A few uses I’m already chasing:

  • Bug-fix-via-Telegram. The PM net is already wired to Telegram. A bug report from a real user becomes a tracked story without any human in the middle.
  • Tier-tuning per net. The Architect can stay on deepseek-671b for architecture work and downgrade to qwen for a routine README-fix story — the inscription tells it which tier this particular fire should use.
  • Replacing the rework heuristic with crystallized rules. After enough rework cycles teach the system “the dev forgot to echo SHA”, that lesson can be crystallized into a deterministic post-step instead of an LLM round-trip.
  • Multi-repo teams. Today there’s one bare repo. Tomorrow each role-net can target a different repo with the same git-push-is-the-deploy pattern.

Try It Yourself

If you have AgenticNetOS running and a safe-teams model deployed, the equivalent injection on your machine is one curl:

# 1. Drop a story into p-pm-inbox
curl -X POST "http://localhost:8082/api/runtime/places/p-pm-inbox/tokens?modelId=safe-teams" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-story","data":{"text":"Your one-sentence request goes here."}}'

# 2. Watch the master log for tier resolution
tail -F /tmp/agentic-net-master.log | grep -E 'Tier-resolved|deploy complete'

# 3. (Optional) Watch the bare repo
git --git-dir=/path/to/git-analytics.git log --oneline -5

This article was written after the run finished, using the actual log lines and commit SHAs from the run. Every timestamp is real. The screenshot of the rendered banner sits in /tmp/safe-teams-live-banner.png on the machine where I ran it.

Related reading: From Human-in-the-Loop to Living Automation for the pattern-crystallization story, and Executors and Deployment Architecture for the polling-based executor pattern that powers Claude-Code runs inside command transitions.

Leave a Reply

Your email address will not be published. Required fields are marked *