DEV Community

Cover image for The First NexFlow CLI Should Refuse to Run Agents
Alex Agafonov
Alex Agafonov

Posted on

The First NexFlow CLI Should Refuse to Run Agents

Give a specification a CLI and someone will eventually ask it to execute the system.

For NexFlow, that would be the most tempting feature to build first and the wrong one.

A command that launches agents makes a better demo than a validator. It also turns early implementation choices into de facto rules before the specification has settled them.

NexFlow currently describes a specification through documentation, YAML manifests, JSON Schemas, reference examples, validation rules, conformance language, and an RFC process. It does not yet provide a production runtime, provider integrations, or a production CLI.

The draft RFC-0011: Reference CLI Scope makes the proposed boundary explicit.

The repository has maintenance commands for schema validation and a semantic reference smoke check. They validate reference manifests and catch a defined set of missing or duplicate cross-manifest references. They are not nexflow CLI commands, a full semantic validator, or a runtime.

The current compatibility matrix records 17 schema-backed manifest kinds, seven reference project sets, and 113 schema-backed manifests. Structural validation is implemented for the maintained examples, while semantic reference checking remains partial. Those numbers describe repository coverage; they do not imply runtime maturity.

This gives the future CLI a concrete starting point: put existing checks behind a stable interface, improve their diagnostics, and remain explicit about everything they do not verify. The initial tool should help people validate and inspect a team definition before any runtime tries to execute it.

What validation-only means

A validation-only CLI has a deliberately limited job: turn a directory of manifests into something a contributor or reviewer can trust enough to discuss.

RFC-0011 proposes four commands with different review jobs.

nexflow validate
nexflow inspect
nexflow graph
Enter fullscreen mode Exit fullscreen mode

validate parses manifests and reports structural or supported semantic problems. It does not call workflows or providers.

inspect summarizes what the project declares without resolving secrets or reading external systems.

graph shows static relationships between tasks, actors, permissions, and handoffs. It does not represent live runtime state.

init creates a small local starter manifest set without installing dependencies, configuring credentials, setting up cloud services, or executing anything.

I use validation-only as shorthand for this non-runtime boundary. init may write starter YAML files locally; none of the proposed commands should run agents.

Why not start with execution

Once the first CLI executes workflows, its implementation choices start behaving like specification decisions. Storage, permission enforcement, credential isolation, provider calls, event logging, rejection handling, and context limits all acquire defaults before the model has settled them.

Convenient defaults are especially hard to remove after examples, CI jobs, and integrations depend on them. A specification-first project needs a more cautious sequence: make manifests readable, validate their structure, add semantic checks across references, and use what we learn to define runtime behavior precisely.

What validate should check first

At the first level, validate should do the unglamorous work that makes later review possible.

It can check:

  • YAML files parse without syntax errors;
  • specVersion is supported;
  • kind matches the expected manifest type;
  • required fields are present;
  • enum values are allowed;
  • basic types match the JSON Schemas;
  • errors point to a file and field path.

These checks remove avoidable noise before human review. If a manifest does not pass structural validation, a debate about its intended meaning starts from unreliable input.

The diagnostic also matters as much as the verdict. A contributor needs the file, field path, stable error code, and a message that explains what the schema expected.

Diagnostics are part of the interface

A validator becomes infrastructure as soon as editors and CI jobs depend on its output. At that point, diagnostics are no longer decorative prose. They are an interface that other tools will parse and people will use to find the problem.

RFC-0011 proposes recording the severity, diagnostic code, file, manifest kind, YAML or JSON path, message, and related references when they help. A machine-readable result could look like this:

{
  "severity": "error",
  "code": "NF-SCHEMA-REQUIRED",
  "file": "examples/minimal-team/agents.yaml",
  "kind": "AgentSet",
  "path": "$.agents[0].id",
  "message": "Required field is missing."
}
Enter fullscreen mode Exit fullscreen mode

Stable codes matter because a CI annotation should not break when someone improves the wording of a message. Human-readable output can remain concise while JSON or a future SARIF mode carries structured fields.

The same honesty applies to partial checks. NexFlow now has a smoke check for core references, while workflow correctness, policy safety, approval sufficiency, and full semantic conformance remain outside its scope. A future CLI should report which checks it ran instead of letting a successful schema pass look like a broader safety guarantee.

Manifest discovery should be visible

Validation also needs a deterministic answer to a basic question: which files were included?

An explicit path is a good initial interface:

nexflow validate examples/minimal-team
Enter fullscreen mode Exit fullscreen mode

Future discovery could accept a project file, a directory, or a defined manifest bundle. It should not wander through parent directories, silently merge unrelated files, or infer a project from whichever YAML happens to be nearby.

inspect can make this boundary visible by listing every manifest it found and every kind it recognized. When validation results differ between a laptop and CI, that inventory is often the first useful piece of evidence.

Inspect before execute

The inspect command is useful before any runtime exists.

It can show what a project actually declares:

  • which participants are part of the team;
  • which capabilities exist;
  • which permissions apply;
  • which actions require approval;
  • which context sources are available;
  • which memory scopes exist;
  • which events should be retained;
  • which extensions and integrations are declared.

The result is a review surface rather than a runtime preview.

Instead of reading a dozen files first, a reviewer can get a compact project map and quickly notice suspicious areas.

If an agent has execute_command, that should be visible. If project memory can be updated automatically, that should be visible. If an MCP server is used for more than reading context, that should be visible too.

Graph as a review tool

The graph command does not need to draw a beautiful diagram first.

Even a text representation of dependencies can be useful.

For example, it could show how tasks connect:

implement-feature -> test-feature -> review-change -> update-docs
Enter fullscreen mode Exit fullscreen mode

Or how responsibility moves between actors:

implementation-agent -> qa-agent -> reviewer -> docs-agent
Enter fullscreen mode Exit fullscreen mode

This kind of map exposes gaps before they become automation problems. A reviewer can see a missing handoff between implementation and documentation, an unsafe dependency-install step without approval, or a QA stage that produces no artifact for the next actor.

The graph makes the work model readable without simulating it.

Exit codes and CI

Even a validation-only CLI can be useful in CI when every result says exactly what was checked.

A hard error should mean the manifest is structurally invalid: a file cannot be read, schema validation fails, a required field is missing, or an enum value is unknown.

A warning should mean the file can be read, but there is a modeling concern: for example, a web source has no citation policy, an approval gate looks too broad, or a memory scope looks risky.

Warnings should not be presented as safety guarantees.

CI should not pretend that it checked something it did not check.

The draft RFC suggests a small exit-code contract. Code 0 means the command completed without errors. Code 1 reports validation or supported semantic errors. Code 2 indicates incorrect command usage, while code 3 marks an unsupported specification version, manifest kind, or requested feature. Code 4 is reserved for an internal CLI failure.

Warnings would normally keep a zero exit code unless an explicit strict mode changes that behavior. This gives teams a usable default without pretending every warning is equally severe.

Extensions should remain inert

NexFlow allows provider and extension metadata without making the core specification provider-specific. A validator therefore needs a conservative policy for extensions it does not understand.

Inspection can preserve and display the metadata. Validation can report that the extension semantics are unsupported. Neither operation should treat an extension as permission to call a service, resolve credentials, or fetch remote context.

That rule keeps the CLI useful in local development and CI environments where read access to repository files should be enough. Extension-aware validation can arrive later through explicit support and documentation instead of an accidental network side effect.

Validation is not execution

A validation-only CLI should not promise more than it does.

It should not:

  • call model providers;
  • run workflows;
  • execute local commands on behalf of an agent;
  • create pull requests;
  • update external systems;
  • store durable memory;
  • enforce permissions in real time.

Those behaviors belong to future runtime work and require their own specification and safety model.

The first job of the CLI is simpler: help people and future tools see what the manifests describe, and catch specification errors before they become behavior errors.

A narrow CLI can still become real infrastructure

A narrow first CLI would still give NexFlow something concrete. Contributors could share the same diagnostics, reviewers could inspect the same project inventory, and CI could reject malformed manifests without installing providers or credentials. Every failure would teach the specification something before runtime behavior becomes fixed around it.

The command-line surface should expand when repository evidence justifies the expansion. Until then, refusing to run agents is part of the contract. Execution can arrive after permissions, approvals, context, memory, events, and compatibility are precise enough to implement without quietly inventing their meaning inside one command.

Top comments (0)