php-agentic/docs/architecture.md

323 lines
13 KiB
Markdown
Raw Normal View History

---
title: Architecture
description: Technical architecture of the core-agentic package
updated: 2026-01-29
---
# Architecture
The `core-agentic` package provides AI agent orchestration infrastructure for the Host UK platform. It enables multi-agent collaboration, persistent task tracking, and unified access to multiple AI providers.
## Overview
```
┌─────────────────────────────────────────────────────────────────┐
│ MCP Protocol Layer │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Plan │ │ Phase │ │ Session │ │ State │ ... tools │
│ │ Tools │ │ Tools │ │ Tools │ │ Tools │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└───────┼────────────┼────────────┼────────────┼──────────────────┘
│ │ │ │
┌───────┴────────────┴────────────┴────────────┴──────────────────┐
│ AgentToolRegistry │
│ - Tool registration and discovery │
│ - Permission checking (API key scopes) │
│ - Dependency validation │
│ - Circuit breaker integration │
└──────────────────────────────────────────────────────────────────┘
┌───────┴──────────────────────────────────────────────────────────┐
│ Core Services │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ AgenticManager │ │ AgentApiKey │ │ PlanTemplate │ │
│ │ (AI Providers) │ │ Service │ │ Service │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ IpRestriction │ │ Content │ │ AgentSession │ │
│ │ Service │ │ Service │ │ Service │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
┌───────┴──────────────────────────────────────────────────────────┐
│ Data Layer │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
│ │ AgentPlan │ │ AgentPhase │ │ AgentSession│ │ AgentApiKey ││
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘│
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Workspace │ │ Task │ │
│ │ State │ │ │ │
│ └─────────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────────────────┘
```
## Core Concepts
### Agent Plans
Plans represent structured work with phases, tasks, and progress tracking. They persist across agent sessions, enabling handoff between different AI models or instances.
```
AgentPlan
├── slug (unique identifier)
├── title
├── status (draft → active → completed/archived)
├── current_phase
└── phases[] (AgentPhase)
├── name
├── tasks[]
│ ├── name
│ └── status
├── dependencies[]
└── checkpoints[]
```
**Lifecycle:**
1. Created via MCP tool or template
2. Activated to begin work
3. Phases started/completed in order
4. Plan auto-completes when all phases done
5. Archived for historical reference
### Agent Sessions
Sessions track individual work periods. They enable context recovery when an agent's context window resets or when handing off to another agent.
```
AgentSession
├── session_id (prefixed unique ID)
├── agent_type (opus/sonnet/haiku)
├── status (active/paused/completed/failed)
├── work_log[] (chronological actions)
├── artifacts[] (files created/modified)
├── context_summary (current state)
└── handoff_notes (for next agent)
```
**Handoff Flow:**
1. Session logs work as it progresses
2. Before context ends, agent calls `session_handoff`
3. Handoff notes capture summary, next steps, blockers
4. Next agent calls `session_resume` to continue
5. Resume session inherits context from previous
### Workspace State
Key-value state storage shared between sessions and plans. Enables agents to persist decisions, configurations, and intermediate results.
```
WorkspaceState
├── key (namespaced identifier)
├── value (any JSON-serialisable data)
├── type (json/markdown/code/reference)
└── category (for organisation)
```
## MCP Tool Architecture
All MCP tools extend the `AgentTool` base class which provides:
### Input Validation
```php
protected function requireString(array $args, string $key, ?int $maxLength = null): string
protected function optionalInt(array $args, string $key, ?int $default = null): ?int
protected function requireEnum(array $args, string $key, array $allowed): string
```
### Circuit Breaker Protection
```php
return $this->withCircuitBreaker('agentic', function () {
// Database operations that could fail
return AgentPlan::where('slug', $slug)->first();
}, fn () => $this->error('Service unavailable', 'circuit_open'));
```
### Dependency Declaration
```php
public function dependencies(): array
{
return [
ToolDependency::contextExists('workspace_id', 'Workspace required'),
ToolDependency::toolCalled('session_start', 'Start session first'),
];
}
```
### Tool Categories
| Category | Tools | Purpose |
|----------|-------|---------|
| `plan` | plan_create, plan_get, plan_list, plan_update_status, plan_archive | Work plan management |
| `phase` | phase_get, phase_update_status, phase_add_checkpoint | Phase operations |
| `session` | session_start, session_end, session_log, session_handoff, session_resume, session_replay | Session tracking |
| `state` | state_get, state_set, state_list | Persistent state |
| `task` | task_update, task_toggle | Task completion |
| `template` | template_list, template_preview, template_create_plan | Plan templates |
| `content` | content_generate, content_batch_generate, content_brief_create | Content generation |
## AI Provider Abstraction
The `AgenticManager` provides unified access to multiple AI providers:
```php
$ai = app(AgenticManager::class);
// Use specific provider
$response = $ai->claude()->generate($system, $user);
$response = $ai->gemini()->generate($system, $user);
$response = $ai->openai()->generate($system, $user);
// Use by name (for configuration-driven selection)
$response = $ai->provider('gemini')->generate($system, $user);
```
### Provider Interface
All providers implement `AgenticProviderInterface`:
```php
interface AgenticProviderInterface
{
public function generate(string $systemPrompt, string $userPrompt, array $config = []): AgenticResponse;
public function stream(string $systemPrompt, string $userPrompt, array $config = []): Generator;
public function name(): string;
public function defaultModel(): string;
public function isAvailable(): bool;
}
```
### Response Object
```php
class AgenticResponse
{
public string $content;
public string $model;
public int $inputTokens;
public int $outputTokens;
public int $durationMs;
public ?string $stopReason;
public array $raw;
public function estimateCost(): float;
}
```
## Authentication
### API Key Flow
```
Request → AgentApiAuth Middleware → AgentApiKeyService::authenticate()
├── Validate key (SHA-256 hash lookup)
├── Check revoked/expired
├── Validate IP whitelist
├── Check permissions
├── Check rate limit
└── Record usage
```
### Permission Model
```php
// Permission constants
AgentApiKey::PERM_PLANS_READ // 'plans.read'
AgentApiKey::PERM_PLANS_WRITE // 'plans.write'
AgentApiKey::PERM_SESSIONS_WRITE // 'sessions.write'
// etc.
// Check permissions
$key->hasPermission('plans.write');
$key->hasAllPermissions(['plans.read', 'sessions.write']);
```
### IP Restrictions
API keys can optionally restrict access by IP:
- Individual IPv4/IPv6 addresses
- CIDR notation (e.g., `192.168.1.0/24`)
- Mixed whitelist
## Event-Driven Boot
The module uses the Core framework's event-driven lazy loading:
```php
class Boot extends ServiceProvider
{
public static array $listens = [
AdminPanelBooting::class => 'onAdminPanel',
ConsoleBooting::class => 'onConsole',
McpToolsRegistering::class => 'onMcpTools',
];
}
```
This ensures:
- Views only loaded when admin panel boots
- Commands only registered when console boots
- MCP tools only registered when MCP module initialises
## Multi-Tenancy
All data is workspace-scoped via the `BelongsToWorkspace` trait:
- Queries auto-scoped to current workspace
- Creates auto-assign workspace_id
- Cross-tenant queries throw `MissingWorkspaceContextException`
## File Structure
```
core-agentic/
├── Boot.php # Service provider with event handlers
├── config.php # Module configuration
├── Migrations/ # Database schema
├── Models/ # Eloquent models
│ ├── AgentPlan.php
│ ├── AgentPhase.php
│ ├── AgentSession.php
│ ├── AgentApiKey.php
│ └── WorkspaceState.php
├── Services/ # Business logic
│ ├── AgenticManager.php # AI provider orchestration
│ ├── AgentApiKeyService.php # API key management
│ ├── IpRestrictionService.php
│ ├── PlanTemplateService.php
│ ├── ContentService.php
│ ├── ClaudeService.php
│ ├── GeminiService.php
│ └── OpenAIService.php
├── Mcp/
│ ├── Tools/Agent/ # MCP tool implementations
│ │ ├── AgentTool.php # Base class
│ │ ├── Plan/
│ │ ├── Phase/
│ │ ├── Session/
│ │ ├── State/
│ │ └── ...
│ ├── Prompts/ # MCP prompt definitions
│ └── Servers/ # MCP server configurations
├── Middleware/
│ └── AgentApiAuth.php # API authentication
├── Controllers/
│ └── ForAgentsController.php # Agent discovery endpoint
├── View/
│ ├── Blade/admin/ # Admin panel views
│ └── Modal/Admin/ # Livewire components
├── Jobs/ # Queue jobs
├── Console/Commands/ # Artisan commands
└── Tests/ # Pest test suites
```
## Dependencies
- `host-uk/core` - Event system, base classes
- `host-uk/core-tenant` - Workspace, BelongsToWorkspace trait
- `host-uk/core-mcp` - MCP infrastructure, CircuitBreaker