# How Agent Zero Facilitates Interaction with the Active Shell: Architecture and Implementation

> Explore how Agent Zero connects with the active shell. Discover its stateful CodeExecution tool for interactive sessions, real-time output streaming, and prompt detection.

- Repository: [Agent Zero/agent-zero](https://github.com/agent0ai/agent-zero)
- Tags: architecture
- Published: 2026-02-23

---

**Agent Zero facilitates interaction with the active shell through a stateful CodeExecution tool that manages persistent interactive sessions—local or remote via SSH—streams real-time output, and automatically detects shell prompts to determine command completion.**

Agent Zero, an open-source AI agent framework in the `agent0ai/agent-zero` repository, provides robust shell interaction capabilities that allow AI agents to execute commands in persistent terminal environments. The framework's **code execution tool** facilitates interaction with the active shell by maintaining stateful sessions across multiple tool invocations, enabling complex multi-step workflows in both local and remote environments.

## Core Architecture for Shell Interaction

The shell interaction system centers on three primary data structures defined in [`python/tools/code_execution_tool.py`](https://github.com/agent0ai/agent-zero/blob/main/python/tools/code_execution_tool.py).

### ShellWrap and State Management

The **`ShellWrap` dataclass** (lines 31‑35) encapsulates an individual shell session:

```python
@dataclass
class ShellWrap:
    id: str
    session: InteractiveSession
    running: bool = False

```

The **`State` dataclass** (lines 38‑40) maintains a dictionary of active shells and tracks whether SSH mode is enabled:

```python
@dataclass
class State:
    shells: dict[str, ShellWrap]
    ssh_enabled: bool

```

These structures persist across tool calls via the agent's data store (`_cet_state`), allowing sessions to survive multiple AI interactions.

### The CodeExecution Tool Class

The **`CodeExecution` class** (starting at line 43) orchestrates the entire lifecycle. It handles session initialization, command dispatch, output streaming, and prompt detection using compiled regex patterns (lines 45‑58) that recognize Bash, PowerShell, and container prompts.

## Session Lifecycle Management

Agent Zero manages shell sessions through a structured lifecycle that supports both local PTY-based terminals and remote SSH connections.

### Creating Local and SSH Sessions (prepare_state)

The `prepare_state()` method (lines 36‑57) initializes or retrieves existing sessions. When `code_exec_ssh_enabled` is true, it instantiates an **`SSHInteractiveSession`** ([`python/helpers/shell_ssh.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_ssh.py), lines 11‑70); otherwise, it creates a **`LocalInteractiveSession`** ([`python/helpers/shell_local.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_local.py), lines 10‑19).

```python

# Core session creation logic from prepare_state

if self.agent.config.code_exec_ssh_enabled:
    shell = SSHInteractiveSession(..., cwd=cwd)
else:
    shell = LocalInteractiveSession(cwd=cwd)
shells[session] = ShellWrap(id=session, session=shell, running=False)
await shell.connect()

```

Both session types implement the `InteractiveSession` interface, providing a consistent API for connection, command execution, and output retrieval.

### Executing Commands (terminal_session)

The `terminal_session()` method serves as the entry point for all terminal-type executions. It marks the session as running and dispatches the command:

```python

# From terminal_session (lines 98-101)

self.state.shells[session].running = True
await self.state.shells[session].session.send_command(command)

```

The `send_command` coroutine writes the command to the underlying PTY (via [`python/helpers/tty_session.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/tty_session.py) for local sessions) or SSH channel, clearing prior output buffers to ensure clean output capture.

### Streaming and Detecting Output (get_terminal_output)

After command dispatch, `get_terminal_output()` enters a streaming loop that:

1. Retrieves output via `session.read_output(timeout=1, reset_full_output=...)`
2. Cleans the output to strip ANSI codes and null bytes (using `clean_string` in SSH sessions)
3. Updates the UI log incrementally
4. Detects completion via **shell prompt patterns** or **dialog patterns**

```python

# Prompt detection logic (lines 90-99)

for pat in self.prompt_patterns:
    if pat.search(line.strip()):
        # Command completed – mark session idle and return

        self.mark_session_idle(session)

```

When a prompt or user-input dialog is detected, the session is marked idle via `mark_session_idle()`, allowing subsequent commands to reuse the session or enabling the UI to prompt the user for input.

### Session Teardown (reset_terminal)

The `reset_terminal()` method closes specific sessions while preserving others:

```python

# Reset logic (lines 42-45)

await self.prepare_state(reset=True, session=session)

```

The underlying `close()` method terminates the PTY process (via `tty_session.TTYSession.kill()`) or shuts down the SSH channel (`SSHInteractiveSession.close()`), ensuring resource cleanup.

## Practical Code Examples

### Example 1: Run a Local Bash Command

```python
await agent.run_tool(
    name="CodeExecution",
    args={
        "runtime": "terminal",
        "code": "ls -la /app",
        "session": 0,          # creates/uses session 0

        "allow_running": False,
    },
)

```

Agent Zero creates a `LocalInteractiveSession`, sends the command, streams the cleaned output back, and automatically stops when it detects the Bash prompt (`$` or `#`).

### Example 2: Open an SSH-Backed Session and Keep It Alive

```python

# First call – initialise SSH session 1

await agent.run_tool(
    name="CodeExecution",
    args={"runtime": "terminal", "code": "uname -a", "session": 1}
)

# Subsequent call – reuse same SSH session

await agent.run_tool(
    name="CodeExecution",
    args={"runtime": "terminal", "code": "df -h", "session": 1}
)

```

Because `session: 1` already exists, `prepare_state()` reuses the existing `SSHInteractiveSession`, preserving the remote working directory and environment variables across calls.

### Example 3: Detect a Dialog and Pause Execution

When a command prompts for confirmation, the tool's dialog patterns trigger an early return with a pause message, allowing the UI to surface a response button.

```python
await agent.run_tool(
    name="CodeExecution",
    args={"runtime": "terminal", "code": "rm -i important.txt", "session": 0}
)

# Output includes: "Detected dialog prompt, returning output early."

```

The UI can then ask the user to confirm the deletion before resuming the session.

## Key Implementation Files

| File | Role | Location |
|------|------|----------|
| [`python/tools/code_execution_tool.py`](https://github.com/agent0ai/agent-zero/blob/main/python/tools/code_execution_tool.py) | Core tool handling session lifecycle, command dispatch, output streaming, prompt/dialog detection. | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/tools/code_execution_tool.py) |
| [`python/helpers/shell_local.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_local.py) | Implements a local PTY-based interactive session. | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_local.py) |
| [`python/helpers/shell_ssh.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_ssh.py) | Provides an SSH-based interactive session with robust UTF-8 handling and output cleaning. | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_ssh.py) |
| [`python/helpers/tty_session.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/tty_session.py) | Low-level wrapper around `pexpect`/PTY for local terminals (used by `LocalInteractiveSession`). | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/tty_session.py) |
| [`python/helpers/print_style.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/print_style.py) | UI-friendly colored logging used throughout the execution flow. | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/print_style.py) |
| [`python/helpers/runtime.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/runtime.py) | Detects platform, provides the terminal executable, and supplies helper functions for development-time calls. | [View on GitHub](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/runtime.py) |

These components together give Agent Zero a **robust, stateful shell interface** that works transparently over local or remote environments, automatically detects completion, and integrates cleanly with the agent's UI and logging infrastructure.

## Summary

- **Agent Zero facilitates interaction with the active shell** through the `CodeExecution` tool, which maintains persistent interactive sessions across multiple AI tool invocations.
- The architecture uses a `ShellWrap` dataclass to encapsulate session state and a `State` dataclass to manage multiple concurrent shells, supporting both local PTY and remote SSH backends.
- Session lifecycle methods—`prepare_state()`, `terminal_session()`, and `get_terminal_output()`—handle connection, command dispatch, and real-time output streaming with automatic prompt detection.
- The system detects command completion via regex patterns matching common shell prompts and can pause execution when user input dialogs are detected, enabling interactive workflows.
- All session state persists in the agent's data store (`_cet_state`), allowing continuous multi-step operations that preserve environment variables and working directories.

## Frequently Asked Questions

### How does Agent Zero maintain shell state across multiple commands?

Agent Zero stores active shell sessions in a `State` dataclass within the agent's persistent data store under the key `_cet_state`. When a tool is invoked, `prepare_state()` retrieves this state or creates a new one if SSH configuration changed. This allows the `ShellWrap` objects—containing the underlying `LocalInteractiveSession` or `SSHInteractiveSession`—to persist across multiple AI interactions, preserving environment variables, working directories, and command history.

### Can Agent Zero execute commands on remote servers via SSH?

Yes, Agent Zero supports remote shell interaction through the `SSHInteractiveSession` class defined in [`python/helpers/shell_ssh.py`](https://github.com/agent0ai/agent-zero/blob/main/python/helpers/shell_ssh.py). When the `code_exec_ssh_enabled` configuration flag is true, `prepare_state()` instantiates an SSH session instead of a local PTY. The SSH session handles UTF-8 encoding, output cleaning, and persistent connections, allowing agents to execute commands on remote hosts while maintaining the same session persistence and prompt detection capabilities as local sessions.

### How does Agent Zero know when a command has finished executing?

Agent Zero detects command completion through regex pattern matching in the `get_terminal_output()` method. The tool compiles a set of `prompt_patterns` (lines 45‑58 in [`python/tools/code_execution_tool.py`](https://github.com/agent0ai/agent-zero/blob/main/python/tools/code_execution_tool.py)) that match common shell prompts such as Bash (`$` or `#`), PowerShell, and container environments. As output streams in, each line is checked against these patterns; when a match is found, the session is marked idle via `mark_session_idle()`, signaling that the command has completed and the output is final.

### What happens when a command prompts for user input?

When a command generates an interactive dialog (e.g., `rm -i` asking for confirmation), Agent Zero's `dialog_patterns` detect the pause in execution. Rather than hanging indefinitely, `get_terminal_output()` returns early with the partial output and a pause indicator, allowing the UI layer to surface a response mechanism to the user. Once the user provides input, the agent can resume the session and continue execution, maintaining the interactive workflow without losing session state.