> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent ctrl streaming

## Overview

Streaming execution provides real-time visibility into agent operations. Instead of waiting
for completion, you see text output and tool calls as they happen. Combine streaming callbacks
with the `AgentCtrlConsoleLogger` for full execution introspection.

Key concepts:

* `executeStreaming()`: Execute with real-time output instead of waiting for completion
* `onText()`: Callback for each text chunk as it arrives
* `onToolUse()`: Callback for each tool call with inputs and outputs
* `AgentCtrlConsoleLogger`: Shows execution lifecycle alongside streaming output
* `withMaxTurns()`: Limit the number of agent loop iterations

## Example

```php theme={null}
<?php
require 'examples/boot.php';

use Cognesy\AgentCtrl\AgentCtrl;
use Cognesy\AgentCtrl\Broadcasting\AgentCtrlConsoleLogger;

// Console logger for execution lifecycle visibility
$logger = new AgentCtrlConsoleLogger(
    useColors: true,
    showTimestamps: true,
    showToolArgs: true,
);

$toolCalls = [];

echo "=== Agent Execution Log ===\n\n";

$response = AgentCtrl::claudeCode()
    ->wiretap($logger->wiretap())
    ->withMaxTurns(10)
    ->onText(function (string $text) {
        // Stream text as it arrives
        echo $text;
    })
    ->onToolUse(function (string $tool, array $input, ?string $output) use (&$toolCalls) {
        // Show each tool call as it happens
        $target = $input['pattern'] ?? $input['file_path'] ?? $input['command'] ?? '';
        if (strlen($target) > 40) {
            $target = '...' . substr($target, -37);
        }
        $toolCalls[] = $tool;
        echo "\n  >> [{$tool}] {$target}\n";
    })
    ->executeStreaming('Find the AgentCtrl class and explain the make() factory method. Be concise.');

echo "\n=== Result ===\n";
if (!$response->isSuccess()) {
    echo "Error: Command failed with exit code {$response->exitCode}\n";
    exit(1);
}
echo "Tools used: " . implode(' > ', $toolCalls) . "\n";
echo "Total tool calls: " . count($toolCalls) . "\n";

if ($response->usage()) {
    echo "Tokens: {$response->usage()->input} in / {$response->usage()->output} out\n";
}
if ($response->cost()) {
    echo "Cost: $" . number_format($response->cost(), 4) . "\n";
}
?>
```

## Expected Output

```
=== Agent Execution Log ===

14:32:15.123 [claude-code] [EXEC] Execution started [model=claude-sonnet-4-5-20250514, prompt=Find the AgentCtrl class...]
14:32:15.234 [claude-code] [PROC] Process started [commands=1]
I'll search for the AgentCtrl class to understand the factory pattern.
14:32:15.456 [claude-code] [TOOL] Glob {pattern=src/**/*AgentCtrl*.php}

  >> [Glob] src/**/*AgentCtrl*.php

I found the AgentCtrl class. Let me examine the make() method.
14:32:16.234 [claude-code] [TOOL] Read {file_path=src/AgentCtrl/AgentCtrl.php}

  >> [Read] src/AgentCtrl/AgentCtrl.php

The make() factory method provides a clean way to instantiate agents by:
1. Accepting an AgentType enum to specify which CLI agent to use
2. Returning a configured AgentCtrl instance
3. Allowing method chaining for further configuration
14:32:17.890 [claude-code] [DONE] Execution completed [exit=0, tools=2, cost=$0.0021, tokens=214]

=== Result ===
Tools used: Glob > Read
Total tool calls: 2
Tokens: 125 in / 89 out
Cost: $0.0021
```

## Key Points

* **Real-time output**: Text appears as the agent generates it, not after completion
* **Console logger**: `AgentCtrlConsoleLogger` shows execution lifecycle alongside streaming output
* **Tool visibility**: See each tool call with its arguments as it executes
* **Progress tracking**: Know what the agent is doing at any moment
* **Same response**: Final response object has same structure as non-streaming execution
* **Fluent interface**: Combine `wiretap()`, `onText()`, `onToolUse()`, and configuration methods
* **Use cases**: Progress bars, interactive UIs, debugging, long-running tasks
