Skip to content

Support background processes and live-streamed bash output #41

Closed

Description

@vicgupta

Problem

The bash tool is fully synchronous: it runs bash -c <command>, buffers
stdout/stderr, and returns the combined output only when the process exits,
killing the process group on timeout (internal/tools/bash.go). Each call is a
fresh process, so cd and exported variables don't carry over (already noted in
the README).

This makes the most common real-world workflows impossible for the agent:

  • Start a dev server or test daemon in one step, then hit it in a later step.
  • Run a long build, watch mode, or migration and react to its output.
  • Interact with a REPL or a CLI that keeps running.

Proposed improvement

Add a small in-process process registry to the tool executor and three new tools
alongside the existing six:

  • start_process — launch bash -c <command> in the background; return a
    process id and the first chunk of output.
  • read_process — return output produced since the last read, with optional
    timeout (block up to N ms for new output) and tail.
  • stop_process — kill the process group and report the exit status and
    trailing output.

Also add an optional stream flag to the foreground bash tool so long output
is emitted as it is produced instead of only at the end.

Processes run as children of tinyagent (reusing the existing setProcessGroup
kill path). On run end, Ctrl-C, or a step/time/cost limit, any surviving
background processes are killed and their tails summarized into the trajectory,
so nothing is left running.

For example, the agent can start_process a server, read_process its startup
log until it reports "listening", run tests against it, then stop_process.

Acceptance criteria

  • Three new tools (start_process, read_process, stop_process) are exposed
    in the tool schema with clear descriptions.
  • A background process keeps running across steps; output is buffered per
    process and read_process returns only new output (no duplication).
  • stop_process kills the whole process group (children included) and reports
    the exit status.
  • The foreground bash tool is unchanged by default; with streaming enabled,
    output appears as it is produced.
  • Surviving processes are always cleaned up on run end, interrupt, and limits;
    no orphaned children remain.
  • The number of concurrent background processes is bounded (configurable) and
    per-process output buffers are capped to avoid unbounded memory.
  • go test ./... passes; tests cover the start/read/stop lifecycle, streaming,
    cleanup on interrupt, and the buffer cap.

Implementation pointers

The change fits in internal/tools/ (a new process.go plus wiring in
tools.go and bash.go), reusing the existing setProcessGroup kill path. The
process registry lives on tools.Executor, scoped per run. A config key (e.g.
max_background_processes) extends internal/config/config.go. Update the
README "Notes" section and the tool-schema descriptions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    amf:readyReady for amf to turn into a pull requestenhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions