Skip to main content

Agent Protocol

Last verified against code: 2026-03-17

Summary

Gas City’s agent runtime boundary lives in internal/runtime/. runtime.Provider is the low-level contract for starting, stopping, attaching to, nudging, and observing agent sessions. The surrounding pieces that make that usable at the product level are:
  • internal/agent/ for session naming and startup hints
  • cmd/gc/template_resolve.go for building runtime start configs
  • internal/session/ for session bead records, waits, and blocked-turn state
The important current-state split is:
  • runtime manages live sessions and I/O
  • agent helpers define naming and startup-hint data
  • session helpers manage higher-level session bookkeeping

Key Concepts

  • runtime.Provider: The core runtime interface in internal/runtime/runtime.go. It owns session lifecycle, communication, metadata, and observation.
  • runtime.Config: Start-time configuration for a session. Includes command, env, working directory, startup hooks, overlays, and copy rules.
  • agent.StartupHints: The resolved config-side hints that are converted into runtime.Config.
  • agent.SessionNameFor(): The single source of truth for runtime session naming, defined in internal/agent/session_name.go.
  • Beacon: A startup identification string generated by internal/runtime/beacon.go so restarted sessions are easy to recognize in tools like /resume.
  • Config fingerprint: A deterministic hash from internal/runtime/fingerprint.go used to detect runtime drift.
  • Dialog dismissal: Shared startup-dialog handling in internal/runtime/dialog.go.
  • Waits and pending interactions: Higher-level blocked-session and wait behavior managed in internal/session/.

Architecture

city config
   |
   v
template resolution
cmd/gc/template_resolve.go
   |
   v
agent.StartupHints + runtime.Config
   |
   v
runtime.Provider
internal/runtime/runtime.go
   |
   +--> tmux
   +--> subprocess
   +--> exec
   +--> k8s
   +--> acp / auto / hybrid routing layers
   |
   v
session bookkeeping
internal/session/

Start Flow

  1. Config and provider defaults are resolved in cmd/gc/.
  2. template_resolve.go builds the final command, env, overlays, staged files, and startup hints.
  3. runtime.Provider.Start() receives a runtime.Config.
  4. Provider-specific startup runs:
    • tmux creates or attaches to a tmux session
    • subprocess launches a child process
    • exec delegates to a script
    • k8s creates or resumes a pod-backed session
  5. Shared helpers handle session fingerprinting, beacons, and startup-dialog dismissal where the provider supports it.

Runtime Operations

runtime.Provider exposes the main operations used throughout the CLI and controller:
  • lifecycle: Start, Stop, Interrupt
  • observation: IsRunning, IsAttached, ProcessAlive, Peek, ListRunning, GetLastActivity
  • interaction: Attach, Nudge, SendKeys
  • metadata: SetMeta, GetMeta, RemoveMeta
  • staging and reapply: CopyTo, RunLive
Optional provider extensions also live in runtime/runtime.go:
  • InteractionProvider
  • IdleWaitProvider
  • ImmediateNudgeProvider

Providers

Invariants

  • Session names come from agent.SessionNameFor() and must be stable for a given city/agent/template combination.
  • Runtime drift detection uses runtime.ConfigFingerprint() rather than ad-hoc field comparisons.
  • Providers must treat Stop as idempotent.
  • ProcessAlive with an empty process list returns true by contract.
  • Metadata is runtime-owned state keyed by session name.
  • Higher-level wait and pending-interaction behavior must layer on top of the runtime contract instead of bypassing it.

Interactions

Depends onHow
internal/agentSession naming and startup-hint structures
internal/configProvider presets and resolved agent settings
internal/sessionSession bead state, wait lifecycle, and blocked-turn helpers
Depended on byHow
cmd/gc/cmd_start.goStarts runtimes for configured agents
cmd/gc/reconcile.goUses runtime liveness and drift signals
cmd/gc/cmd_session.goAttach, list, inspect, and session-level commands
cmd/gc/cmd_nudge.goIdle-aware and queued nudge delivery
internal/api/Session-aware API surfaces and status views

Code Map

PathResponsibility
internal/runtime/runtime.goProvider, Config, optional runtime extensions
internal/runtime/fingerprint.goDeterministic runtime config hashing
internal/runtime/beacon.goStartup beacon formatting
internal/runtime/dialog.goShared startup-dialog handling
internal/runtime/fake.goIn-memory fake runtime for tests
internal/runtime/tmux/Interactive tmux-backed runtime
internal/runtime/subprocess/Non-interactive subprocess runtime
internal/runtime/exec/Script-backed runtime provider
internal/runtime/k8s/Kubernetes-backed runtime provider
internal/runtime/acp/ACP-backed runtime provider
internal/runtime/auto/Automatic routing between runtime backends
internal/runtime/hybrid/Hybrid routing between local and remote backends
internal/agent/hints.goStartupHints
internal/agent/session_name.goSession naming
cmd/gc/template_resolve.goBuilds runtime configs from resolved agent config
internal/session/manager.goHigher-level session manager for session beads
internal/session/waits.goWait state helpers

Testing

  • internal/runtime/runtimetest/conformance.go provides runtime conformance coverage
  • internal/runtime/fake_test.go and internal/runtime/fake_conformance_test.go validate the fake runtime
  • internal/runtime/tmux/ contains tmux unit and startup tests
  • internal/runtime/k8s/provider_test.go covers the Kubernetes provider
  • internal/session/manager_test.go and internal/session/manager_states_test.go cover higher-level session bookkeeping layered on top of the runtime

Known Limitations

  • Provider capabilities differ: interactive attach, idle waiting, and pending interactions are not uniformly supported everywhere.
  • Metadata persistence depends on the backing provider.
  • Session bookkeeping and runtime execution are deliberately separate, which means some contributor workflows need to inspect both internal/runtime/ and internal/session/.

See Also

Last modified on March 20, 2026