Skip to content

Add agent output mode (NXF_AGENT_MODE)#6782

Merged
pditommaso merged 16 commits intomasterfrom
agent-output-mode
Feb 28, 2026
Merged

Add agent output mode (NXF_AGENT_MODE)#6782
pditommaso merged 16 commits intomasterfrom
agent-output-mode

Conversation

@edmundmiller
Copy link
Member

@edmundmiller edmundmiller commented Jan 29, 2026

Summary

Add AI agent-friendly output mode for Nextflow, triggered by environment variables:

  • NXF_AGENT_MODE=true
  • AGENT=1
  • CLAUDECODE=1

When enabled, Nextflow outputs a minimal format optimized for AI agent context windows.

Inspired by Bun's test agent mode

Output Format

[PIPELINE] nf-core/rnaseq 3.14.0 | profile=test,docker
[WORKDIR] /path/to/work
[PROCESS b8/623fc3] sayHello (3)
[PROCESS 5f/761e51] sayHello (2)

[WARN] Task runtime metrics are not reported when using macOS

[ERROR] FASTQC (sample_1)
exit: 127
cmd: fastqc --version
stderr: bash: fastqc: command not found
workdir: /path/to/work/ab/123456

[SUCCESS] completed=10 failed=0 cached=5

Key Features

  • Suppresses ASCII banner, ANSI progress, and parameter dumps
  • Prints each process submission with task hash and name
  • Deduplicates warning messages
  • Includes full error context (exit code, command, stderr, workdir)
  • One-line summary at completion
  • All output written to stderr

Architecture

  • LogObserver interface — common abstraction for AnsiLogObserver and AgentLogObserver, allowing Session and LoggerHelper to work through a single logObserver field
  • AgentLogObserverTraceObserverV2 + LogObserver implementation for minimal output
  • DefaultObserverFactory — creates both ANSI and agent observers using the same pattern
  • SysEnv.isAgentMode() — detects agent mode via env vars

Token Savings

Experiments show 98-100% token savings while preserving all diagnostic information:

  • Raw output: 733,399 tokens (11k lines)
  • Agent output: 76 tokens (13 lines)

Tests

  • AgentLogObserverTest — output formatting tests
  • AnsiLogObserverTest — ANSI observer tests (unchanged behavior)
  • SysEnvTestisAgentMode() detection tests

@netlify
Copy link

netlify bot commented Jan 29, 2026

Deploy Preview for nextflow-docs-staging canceled.

Name Link
🔨 Latest commit 18ff87e
🔍 Latest deploy log https://app.netlify.com/projects/nextflow-docs-staging/deploys/69a2bae57438370008eb8671

@edmundmiller edmundmiller self-assigned this Jan 29, 2026
@edmundmiller edmundmiller marked this pull request as ready for review January 29, 2026 19:22
@pditommaso
Copy link
Member

Interesting, but does it still need ansi escape capabilities?

@edmundmiller
Copy link
Member Author

edmundmiller commented Jan 29, 2026

No, agent mode doesn't need ANSI escape capabilities. The implementation explicitly disables ANSI output.

The feature was intentionally designed this way. When NXF_AGENT=true:

  • session.ansiLog = false
  • session.agentLog = true
  • No AnsiLogObserver created
  • Only AgentLogObserver outputs (plain text)
  • Banner/launch info suppressed
    So the terminal doesn't need ANSI capabilities at all - output is pure ASCII text suitable for AI parsing.

@pditommaso
Copy link
Member

Nice!

Copy link
Member

@ewels ewels left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

Haven't tested but a skim of the code on my phone looks sensible / as I'd expect 👍🏻

@pditommaso
Copy link
Member

is the output format complete for this?

@pditommaso
Copy link
Member

This works better with ansi-mode false

» AGENT=1 nextflow run hello
NOTE: Your local project version looks outdated - a different revision is available in the remote repository [d828daeef7]
[PIPELINE] main.nf | profile=standard
[WORKDIR] /Users/pditommaso/Projects/nextflow/work
Bonjour world!

Ciao world!

Hola world!

Hello world!
» AGENT=1 NXF_ANSI_LOG=false nextflow run hello 
[PIPELINE] main.nf | profile=standard
[WORKDIR] /Users/pditommaso/Projects/nextflow/work
[98/2b8d30] Submitted process > sayHello (2)
[f8/89382c] Submitted process > sayHello (1)
[88/b52911] Submitted process > sayHello (3)
[4e/d814a8] Submitted process > sayHello (4)
Hello world!

Ciao world!

Hola world!

Bonjour world!


[SUCCESS] completed=4 failed=0 cached=0

edmundmiller and others added 9 commits February 9, 2026 08:38
Tests for AI agent-friendly output mode via env vars.
All tests marked @PendingFeature until implementation.

Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Add AI agent-friendly output mode triggered by env vars:
- NXF_AGENT=true
- AGENT=true
- CLAUDECODE=true

When enabled, outputs minimal structured format:
- [PIPELINE] name version | profile=X
- [WORKDIR] path
- [WARN] deduplicated warnings
- [ERROR] with exit/cmd/stderr/workdir context
- [SUCCESS|FAILED] summary

Achieves 98-100% token savings for AI context windows.

Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
- agent-output.nf: Tests successful workflow in agent mode
- agent-output-error.nf: Tests error output format in agent mode
- Validates [PIPELINE], [WORKDIR], [SUCCESS/FAILED] format
- Verifies banner suppression and error context (exit code, workdir)

Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Co-authored-by: Ben Sherman <bentshermann@gmail.com>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Co-authored-by: Ben Sherman <bentshermann@gmail.com>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Only one observer is ever active. Use instanceof for ANSI-specific
features (appendSticky, started/stopped checks).

Co-authored-by: Ben Sherman <bentshermann@gmail.com>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
Task hashes and submission lines flow through ConsoleAppender instead
of being captured and suppressed.

Co-authored-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
…t mode

AgentLogObserver.println wrote to System.out but integration tests
capture stderr. Also enable CaptureAppender in agent mode so log-level
warnings/errors are forwarded to the observer.

Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
printConsole was routing view operator output through
logObserver.appendInfo() which suppresses most messages in agent mode.
Only AnsiLogObserver needs to capture console output for rendering.

Signed-off-by: Edmund Miller <edmund.miller@seqera.io>
pditommaso and others added 4 commits February 28, 2026 09:38
Remove the LogObserver interface abstraction and reference each
observer by its concrete type. Session now holds separate
ansiLogObserver and agentLogObserver fields so neither mode
pollutes the other.

Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Add LogObserver interface as common abstraction for AnsiLogObserver and
AgentLogObserver. Session now holds a single logObserver field instead of
two concrete fields. Move AgentLogObserver creation to DefaultObserverFactory
to match AnsiLogObserver pattern. Print process submissions in agent mode.
Rename NXF_AGENT env var to NXF_AGENT_MODE. Add env var documentation.

Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
@pditommaso pditommaso requested a review from a team as a code owner February 28, 2026 09:20
@pditommaso pditommaso changed the title Add agent output mode (NXF_AGENT) Add agent output mode (NXF_AGENT_MODE) Feb 28, 2026
Signed-off-by: Paolo Di Tommaso <paolo.ditommaso@gmail.com>
@pditommaso
Copy link
Member

Update on output streams: After testing, the agent mode structured output ([PIPELINE], [PROCESS], [WARN], [ERROR], [SUCCESS]/[FAILED]) goes to stdout rather than stderr. This is because the CaptureAppender routes log events through LogObserver.appendInfoSystem.out, and the observer's lifecycle methods (onFlowBegin, onTaskSubmit, etc.) also end up on stdout via the same path.

This means both structured agent output and workflow output (e.g. from the view operator) share stdout. Tests have been updated accordingly.

We can revisit this in the future if separating structured output (stderr) from workflow output (stdout) becomes necessary — that would require changes to the CaptureAppender routing logic.

@pditommaso pditommaso merged commit eae9f7d into master Feb 28, 2026
10 of 12 checks passed
@pditommaso pditommaso deleted the agent-output-mode branch February 28, 2026 09:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants