<?php
require 'examples/boot.php';
use Cognesy\Agents\Builder\AgentBuilder;
use Cognesy\Agents\Capability\Bash\BashTool;
use Cognesy\Agents\Capability\Core\UseGuards;
use Cognesy\Agents\Capability\Core\UseTools;
use Cognesy\Agents\Capability\File\ListDirTool;
use Cognesy\Agents\Capability\File\ReadFileTool;
use Cognesy\Agents\Capability\File\SearchFilesTool;
use Cognesy\Agents\Capability\PlanningSubagent\UsePlanningSubagent;
use Cognesy\Agents\Collections\NameList;
use Cognesy\Agents\Collections\Tools;
use Cognesy\Agents\Data\AgentState;
use Cognesy\Agents\Data\ExecutionBudget;
use Cognesy\Agents\Enums\ExecutionStatus;
use Cognesy\Agents\Events\Support\AgentEventConsoleObserver;
use Cognesy\Messages\Messages;
$logger = new AgentEventConsoleObserver(
useColors: true,
showTimestamps: true,
showContinuation: true,
showToolArgs: true,
);
$workDir = dirname(__DIR__, 3);
$parentExecutionTools = ['read_file'];
$parentToolsList = implode(', ', $parentExecutionTools);
$agent = AgentBuilder::base()
->withCapability(new UseTools(
ReadFileTool::inDirectory($workDir),
))
->withCapability(new UsePlanningSubagent(
parentInstructions: <<<PROMPT
For tasks that involve multiple implementation steps, call `plan_with_subagent` first.
Parent execution tools available (hard constraint): {$parentToolsList}
When you execute after planning, use only the parent execution tools listed above.
When calling `plan_with_subagent`, provide a task specification with these sections:
- Goal
- Context
- Constraints
- Expected Outcomes
- Acceptance Criteria
PROMPT,
plannerSystemPrompt: <<<PROMPT
You are a planning specialist.
Create a dense markdown plan with explicit checkpoints and tool-aware execution steps.
Use discovery tools (`bash`, `search_files`, `list_dir`) to inspect local context if needed.
Use `bash` with `rg` for fast discovery when helpful.
Do not implement changes.
Parent execution tools (must be respected by the final plan): {$parentToolsList}
All execution steps in the final plan must be feasible using only those parent tools.
PROMPT,
plannerTools: new NameList('bash', 'search_files', 'list_dir', 'read_file'),
plannerAdditionalTools: new Tools(
BashTool::inDirectory($workDir),
SearchFilesTool::inDirectory($workDir),
ListDirTool::inDirectory($workDir),
),
plannerBudget: new ExecutionBudget(maxSteps: 3, maxTokens: 3072, maxSeconds: 30),
))
->withCapability(new UseGuards(maxSteps: 8, maxTokens: 12288, maxExecutionTime: 90))
->build()
->wiretap($logger->wiretap());
$task = <<<'TASK'
Prepare a realistic plan for a small docs update about planning capability in this repository.
First, create a plan.
Then execute only the analysis part of the plan and provide a concise proposal:
1. Capability purpose section outline
2. Configuration options outline
3. Example usage outline
Constraints:
- planner subagent may use bash/search for discovery
- parent execution may use only read_file
- do not modify any files
- keep the final response under 180 words
TASK;
$state = AgentState::empty()->withMessages(
Messages::fromString($task)
);
echo "=== Agent Execution Log ===\n";
echo "Task: Plan first, then execute\n\n";
$finalState = $agent->execute($state);
echo "\n=== Result ===\n";
$answer = $finalState->finalResponse()->toString() ?: 'No answer';
echo "Answer: {$answer}\n";
echo "Steps: {$finalState->stepCount()}\n";
echo "Tokens: {$finalState->usage()->total()}\n";
echo "Status: {$finalState->status()->value}\n";
if ($finalState->status()->value === 'failed') {
echo "Skipping assertions because execution status is failed.\n";
return;
}
$hasAnswer = trim($finalState->finalResponse()->toString()) !== '';
$isStopped = $finalState->status() === ExecutionStatus::Stopped;
assert($hasAnswer || $isStopped, 'Expected non-empty response or stopped status');
assert($finalState->stepCount() >= 1, 'Expected at least 1 step');
assert($finalState->usage()->total() > 0, 'Expected token usage > 0');
?>