StatusCompleted
PriorityHigh
Has UIYes
Sourcerich

Cogniflow Orchestrator

A CLI-driven orchestration engine that runs multi-agent Claude pipelines — sequential DAGs or cyclic, feedback-driven agent graphs — entirely through a Claude subscription, with no API key and no HTTP calls.

01 — THE PROBLEM

Once you try to run more than one Claude call in sequence and have them actually cooperate — an architect agent handing off to a developer, a developer answering back to the architect, a reviewer blocking a step until a human signs off — you’re not writing prompts anymore, you’re writing a distributed system. Retries, timeouts, malformed output, agents stepping on each other’s context, secrets leaking into logs, no record of who approved what. Most people patch this together per-project and end up rebuilding the same plumbing every time.

That’s not just a solo-developer problem. Any team standing up multi-agent workflows — content pipelines, code-review bots, support-ticket triage, compliance drafting — hits the same wall: they need approval gates a human can actually act on, an audit trail of what data moved where, and a way to keep secrets out of both prompts and logs, before the workflow is trustworthy enough to run unattended in a business process.

02 — THE APPROACH

Cogniflow Orchestrator is a Python CLI (`cli.py`) with nine commands: `run` a pipeline (DAG or cyclic, auto-detected or forced), `validate` a pipeline directory before you burn a run on a config typo, `status` and `watch –follow` to see what’s happening live, `inspect` to pull any agent’s output/context/summary/token-budget/history file, `reset` to clear an agent’s state, `approve`/`reject` to act on a pipeline that’s paused waiting on a human, and `hooks install` to wire Claude Code’s hook system into a pipeline. Pipelines are defined in JSON: a DAG is just agents with `depends_on`; a cyclic graph adds typed edges (`task` = one-shot trigger, `feedback` = bidirectional persistent channel, `peer` = peer-to-peer) so agents can loop back and forth — PM to architect to developer and back — until they converge or hit a cycle/deadlock limit.

What it actually does for you: every agent’s input and output can be checked against a JSON schema before and after the Claude call, so a malformed upstream response gets caught instead of silently poisoning the next agent. Any agent can be turned into an approval gate (`requires_approval: true`) that blocks the pipeline until someone runs `cli.py approve` or `reject` — and on rejection in a cyclic graph, the engine routes structured feedback straight to a target agent instead of just failing the run. Secrets never touch a prompt or a log: you write `<<secret:NAME>>` placeholders, the orchestrator rehydrates the real value only for the outbound call and scans inbound responses to catch any leak, with every substitution recorded (names, never values) in an audit table. In cyclic mode, each agent gets a five-file memory directory — full history, a compressed structured summary of decisions and open questions, a rolling recent-turns window, a searchable chunk index, and a token-budget ledger — so long-running agent conversations don’t blow the context window or lose track of earlier decisions.

One thing worth being upfront about: the companion Observer/Configurator UI advertises eight agent “type” labels (worker, reviewer, router, classifier…), but I found — and documented — that only two things actually change execution at runtime: whether `requires_approval` is set, and whether `router.routes` is configured. The other type labels are prompt-template scaffolding, not runtime behavior. That distinction matters if you’re debugging why a “reviewer” agent isn’t blocking anything.

03 — WHAT I LEARNED

The biggest lesson was catching my own UI/engine mismatch before it shipped: the Configurator’s type dropdown implies eight distinct agent behaviors, but tracing the actual code showed only two runtime-relevant flags plus graph mode. I wrote that gap up explicitly (with open questions I hadn’t resolved yet — how routers behave differently in DAG vs. cyclic mode, whether a silent no-op on an unmatched routing decision should instead be a tracked event) rather than let a plausible-looking UI abstraction stand in for what the code does. That’s the general habit: when you’re building both the interface and the engine, audit them against each other regularly, because the interface will happily suggest capabilities the engine doesn’t have.

The second lesson was architectural: separating “what changed and why” (a working log tied to two design docs, `agent-engineering.md` and `ui-engineering.md`) from the README meant the engine and UI sides always had one place to agree on artifact contracts and event names before either side touched code — the kind of discipline that keeps a two-repo project (orchestrator + UI) from drifting apart silently.

04 — WHERE THIS COULD GO

The natural extension is the plugin system already staged for it: a `team_lead` agent type that delegates to Claude Code’s own Task tool with write-scope enforcement and budget caps, plus deferred `aggregator` and `iterator` types once that pattern proves out. For a team, that’s the difference between “a script that calls an LLM” and a governed workflow: schema-checked handoffs, human approval gates with a real audit trail, secrets that never appear in a log, and a CLI anyone on the team can run, inspect, and reset without reading the source.

At org scale this is the shape a lot of “AI agent platform” vendors are selling — the difference here is it runs on a Claude subscription instead of metered API calls, and every contract (schemas, events, approval routes) is a plain JSON file you can diff in a PR, not a config buried in a SaaS dashboard.

05 — TAKEAWAY

It’s a working answer to “how do I run more than one cooperating Claude agent without building a distributed system from scratch” — and building it taught me more about where UI and engine quietly disagree than any single feature did.

Text summarized and optimized using Anthropic’s models and reviewed by a human.