undergrace/laravel-mbc

Model Backend Controller - AI agent orchestration protocol for Laravel

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/undergrace/laravel-mbc

v0.1.0 2026-02-21 06:39 UTC

This package is auto-updated.

Last update: 2026-02-21 07:32:25 UTC


README

AI Agent Orchestration Protocol for Laravel

MBC allows your Laravel backend to orchestrate AI agents as autonomous workers with tools, server-side — no desktop client needed.

🎬 [Watch Demo: 3 AI Agents Build a Website in 34s for $0.34] (https://youtu.be/A_GiAqIWJxE)

Installation

composer require undergrace/laravel-mbc

Publish the configuration:

php artisan vendor:publish --tag=mbc-config

Run migrations:

php artisan migrate

Configuration

Add your API keys to .env depending on the provider you want to use:

# Default provider (anthropic, openai, or openrouter)
MBC_PROVIDER=anthropic

# Anthropic (Claude)
ANTHROPIC_API_KEY=sk-ant-...

# OpenAI (GPT-4o, o1, o3)
OPENAI_API_KEY=sk-...

# OpenRouter (200+ models: Claude, GPT, Gemini, Llama, Mistral, DeepSeek...)
OPENROUTER_API_KEY=sk-or-...

Supported Providers

Provider Models Tool Use Config Key
Anthropic Claude Sonnet 4.5, Opus 4, Haiku 3.5 Native anthropic
OpenAI GPT-4o, o1, o3, o3-mini Native openai
OpenRouter 200+ models from all providers OpenAI-compatible openrouter

Set the default provider in config/mbc.php:

'default_provider' => env('MBC_PROVIDER', 'anthropic'),

Quick Start

use Undergrace\Mbc\Facades\Mbc;

$session = Mbc::session('my-agent')
    ->systemPrompt('You are an assistant that helps organize data.')
    ->tools([
        ListItemsTool::class,
        CreateReportTool::class,
    ])
    ->context(['user_id' => 1, 'department' => 'sales'])
    ->config(maxTurns: 20, model: 'claude-sonnet-4-5-20250929')
    ->start('Analyze the sales data and create a summary report.');

$result = $session->result();
echo $result->finalMessage;

Using Different Providers Per Session

// Claude via Anthropic (direct)
Mbc::session('designer')
    ->config(model: 'claude-sonnet-4-5-20250929')
    ->start('Design the database schema.');

// GPT-4o via OpenAI
Mbc::session('copywriter')
    ->config(model: 'gpt-4o')
    ->start('Write compelling product descriptions.');

// Any model via OpenRouter
Mbc::session('analyst')
    ->config(model: 'anthropic/claude-sonnet-4')
    ->start('Analyze quarterly data.');

// Gemini via OpenRouter
Mbc::session('researcher')
    ->config(model: 'google/gemini-2.5-pro')
    ->start('Research market trends.');

Creating Tools

Generate a tool scaffold:

php artisan mbc:make-tool AnalyzeDataTool

Define tools with PHP Attributes:

use Undergrace\Mbc\Tools\Attributes\Tool;
use Undergrace\Mbc\Tools\Attributes\ToolParam;
use Undergrace\Mbc\Tools\BaseTool;

#[Tool(
    name: 'analyze_data',
    description: 'Analyzes data from the specified table and returns statistics'
)]
class AnalyzeDataTool extends BaseTool
{
    public function __construct(
        private DataRepository $dataRepo,
    ) {}

    #[ToolParam(name: 'table', type: 'string', description: 'Table name to analyze', required: true)]
    #[ToolParam(name: 'metric', type: 'string', description: 'Metric to calculate', enum: ['avg', 'sum', 'count'])]
    public function execute(array $input): mixed
    {
        return $this->dataRepo->analyze($input['table'], $input['metric']);
    }
}

Inter-Agent Communication

MBC provides three patterns for multi-agent collaboration:

Pipeline (Sequential Chaining)

Each agent receives the previous agent's result as context. Ideal for workflows where Agent A's output feeds into Agent B.

use Undergrace\Mbc\Core\MbcPipeline;

$result = MbcPipeline::create()
    ->pipe($architectSession, 'Design the database schema')
    ->pipe($backendSession, 'Implement the API based on the schema')
    ->pipe($frontendSession, 'Create the UI components for the API')
    ->run();

if ($result->successful()) {
    echo $result->final()->finalMessage;
}

echo "Total cost: $" . $result->totalCost();
echo "Stages: " . $result->stageCount();

Orchestrator (Parallel Execution)

Run multiple agents simultaneously and collect results. Ideal for independent tasks that can execute in parallel.

use Undergrace\Mbc\Core\MbcOrchestrator;

// Async via queue
$orchestrator = MbcOrchestrator::create('build-site')
    ->agent($designerSession, 'Design the layout')
    ->agent($copywriterSession, 'Write the content')
    ->agent($seoSession, 'Optimize for search engines')
    ->dispatch();

// Check progress
$progress = $orchestrator->progress();
// ['total' => 3, 'completed' => 2, 'running' => 1, 'failed' => 0, 'pending' => 0]

// Collect when done
if ($orchestrator->isComplete()) {
    $results = $orchestrator->results();
    echo "Total cost: $" . $results->totalCost();
}

// Or run synchronously (blocking)
$results = MbcOrchestrator::create('quick-task')
    ->agent($agentA, 'Task A')
    ->agent($agentB, 'Task B')
    ->runSync();

Sub-Agents (Spawn from within a Session)

An agent can spawn specialized sub-agents during execution using the built-in SpawnAgentTool.

use Undergrace\Mbc\Tools\SpawnAgentTool;

$spawnTool = new SpawnAgentTool();
$spawnTool
    ->register(
        name: 'researcher',
        systemPrompt: 'You research and gather information.',
        toolClasses: [WebSearchTool::class, ReadFileTool::class],
        maxTurns: 10,
    )
    ->register(
        name: 'writer',
        systemPrompt: 'You write content based on research.',
        toolClasses: [WriteFileTool::class],
        maxTurns: 15,
    );

$session = Mbc::session('coordinator')
    ->systemPrompt('You coordinate research and writing tasks. Use spawn_agent to delegate.')
    ->tools([
        $spawnTool,
        OtherTool::class,
    ])
    ->start('Research and write an article about Laravel.');

Shared Context (Memory between Agents)

Agents can share data through a key-value store backed by Laravel's cache system.

use Undergrace\Mbc\Core\MbcContext;

// In Agent A's tool
$ctx = new MbcContext('project-123');
$ctx->set('schema', $databaseSchema);
$ctx->push('decisions', 'Use PostgreSQL for main DB');

// In Agent B's tool (same namespace)
$ctx = new MbcContext('project-123');
$schema = $ctx->get('schema');
$decisions = $ctx->get('decisions'); // ['Use PostgreSQL for main DB']

// Get everything
$all = $ctx->all();

// Clean up when done
$ctx->flush();

Background Execution

use Undergrace\Mbc\Jobs\RunMbcSessionJob;

$session = Mbc::session('background-agent')
    ->systemPrompt('...')
    ->tools([...])
    ->context([...]);

RunMbcSessionJob::dispatch(
    $session->toSerializable(),
    'Your initial message here'
);

The job includes automatic retry logic (3 attempts with 10s, 30s, 60s backoff) and zombie session cleanup on failure.

Middleware

MBC includes built-in middleware and supports custom middleware:

use Undergrace\Mbc\Middleware\LogTurns;
use Undergrace\Mbc\Middleware\CostTracker;
use Undergrace\Mbc\Middleware\RateLimiter;

$session = Mbc::session('with-middleware')
    ->middleware([
        LogTurns::class,
        CostTracker::class,
        RateLimiter::max(30),
    ])
    ->start('...');
Middleware Description
LogTurns Logs each turn's response metadata and optionally full text
CostTracker Tracks cumulative token usage and estimated cost per session
RateLimiter Throws exception if session exceeds max turns
VisualFeedback Captures screenshots for visual feedback loops

Global middleware can be configured in config/mbc.php:

'middleware' => [
    LogTurns::class,
    CostTracker::class,
],

Scalability Features

Context Window Management

Sessions automatically trim old messages when approaching the context window limit, preserving the initial context and most recent turns:

$session = Mbc::session('long-task')
    ->config(
        maxTurns: 50,
        // Context window settings (defaults shown)
        // contextWindowLimit: 150000,
        // contextReserveTokens: 20000,
    )
    ->start('...');

Concurrency Guard

Prevents overloading the system with too many simultaneous sessions:

// config/mbc.php
'limits' => [
    'max_concurrent_sessions' => 10,
],

Zombie Session Cleanup

Sessions stuck in RUNNING state are automatically handled:

# Mark sessions stuck for 60+ minutes as FAILED
php artisan mbc:cleanup

# Custom timeout
php artisan mbc:cleanup --timeout=30

# Also prune old sessions
php artisan mbc:cleanup --prune

Schedule it in your routes/console.php or kernel:

Schedule::command('mbc:cleanup --prune')->hourly();

Dynamic Cost Tracking

Costs are estimated per model using ModelPricing, supporting all providers:

use Undergrace\Mbc\Core\ModelPricing;

$cost = ModelPricing::estimate('claude-sonnet-4-5-20250929', inputTokens: 50000, outputTokens: 10000);
// $0.30

$cost = ModelPricing::estimate('google/gemini-2.5-flash', inputTokens: 50000, outputTokens: 10000);
// $0.01

Persistence

All sessions and turns are stored in the database by default:

  • mbc_sessions — Session metadata, status, cost, result
  • mbc_turns — Each turn's content, tool calls, tool results, tokens

Configure in config/mbc.php:

'storage' => [
    'persist_sessions' => true,
    'persist_turns' => true,
    'prune_after_days' => 30,
],

Artisan Commands

# Generate a new tool
php artisan mbc:make-tool {ToolName}

# Check session status
php artisan mbc:session-status {uuid}

# Replay a previous session
php artisan mbc:replay {uuid}

# Cleanup zombie sessions and prune old data
php artisan mbc:cleanup [--timeout=60] [--prune]

Real-time Broadcasting (WebSockets)

MBC broadcasts all agent events via Laravel's broadcasting system. Works with Reverb, Pusher, Ably, or any supported driver.

Enable in .env:

MBC_BROADCASTING_ENABLED=true

Listening to a specific agent

Echo.channel('mbc.sessions.' + uuid)
    .listen('MbcSessionStarted', (e) => {
        console.log('Agent started:', e.session_name);
    })
    .listen('MbcTurnCompleted', (e) => {
        console.log('Turn', e.turn_number, '- Stop:', e.stop_reason);
    })
    .listen('MbcToolExecuted', (e) => {
        console.log('Tool:', e.tool_name, '- Duration:', e.duration_ms + 'ms');
    })
    .listen('MbcSessionCompleted', (e) => {
        console.log('Done! Cost: $' + e.estimated_cost_usd);
    })
    .listen('MbcSessionFailed', (e) => {
        console.error('Failed:', e.error);
    });

Monitoring all agents (dashboard)

Echo.channel('mbc.monitor')
    .listen('MbcSessionStarted', (e) => {
        // New agent started working
    })
    .listen('MbcSessionCompleted', (e) => {
        // Agent finished
    });

Events broadcast data

Event Data
MbcSessionStarted session_uuid, session_name, timestamp
MbcTurnCompleted session_uuid, turn_number, type, stop_reason, timestamp
MbcToolExecuted session_uuid, tool_name, tool_input, is_error, duration_ms, timestamp
MbcSessionCompleted session_uuid, status, final_message, total_turns, total_tokens, estimated_cost_usd, timestamp
MbcSessionFailed session_uuid, error, timestamp

Configure the channel prefix in config/mbc.php:

'broadcasting' => [
    'enabled' => env('MBC_BROADCASTING_ENABLED', false),
    'channel_prefix' => 'mbc',
],

REST API

Read-only API endpoints for querying sessions, turns, and stats. Enable in .env:

MBC_API_ENABLED=true

Endpoints

Method URI Description
GET /mbc/sessions List sessions (filters: status, from, to, name, model)
GET /mbc/sessions/{uuid} Session detail with turns
GET /mbc/sessions/{uuid}/turns Paginated turn timeline
GET /mbc/stats Aggregate stats (costs, tokens, counts)
GET /mbc/agents/active Currently running/pending sessions

Configuration

// config/mbc.php
'api' => [
    'enabled' => env('MBC_API_ENABLED', false),
    'prefix' => 'mbc',
    'middleware' => ['api'],  // Add 'auth:sanctum' for auth
],

Example requests

# List running sessions
curl /mbc/sessions?status=running

# Get session detail with turns
curl /mbc/sessions/550e8400-e29b-41d4-a716-446655440000

# Get turns timeline
curl /mbc/sessions/550e8400.../turns?per_page=20

# Get aggregate stats for a date range
curl /mbc/stats?from=2026-02-01&to=2026-02-28

# Get active agents
curl /mbc/agents/active

Logging

MBC auto-registers its own log channel. Logs are written to storage/logs/mbc.log:

// config/mbc.php
'logging' => [
    'channel' => 'mbc',
    'log_prompts' => env('MBC_LOG_PROMPTS', false),
    'log_responses' => env('MBC_LOG_RESPONSES', false),
],

License

MIT - UNDERGRACE LABS