Toolboxes let you group related tools into logical collections with built-in authorization support. Think of them as “tool bundles” that can be enabled or disabled based on user permissions, subscription tiers, or any other context.
Organized Tools Group related tools together for cleaner agent definitions
Built-in Authorization Use Laravel Gates and Policies at both toolbox and tool levels
Dynamic Loading Tools are loaded on-demand based on user context
Runtime Flexibility Add or remove toolboxes at runtime based on conditions
The easiest way to use toolboxes is to declare them in your agent’s $toolboxes property:
app/Agents/CustomerAgent.php
<? php
namespace App\Agents ;
use App\Toolboxes\ CustomerSupportToolbox ;
use App\Toolboxes\ OrderManagementToolbox ;
use Vizra\VizraADK\Agents\ BaseLlmAgent ;
class CustomerAgent extends BaseLlmAgent
{
protected string $name = 'customer_agent' ;
protected string $description = 'Helps customers with support and orders' ;
protected string $instructions = 'You are a helpful customer support agent.' ;
protected array $toolboxes = [
CustomerSupportToolbox :: class ,
OrderManagementToolbox :: class ,
];
// You can also include individual tools alongside toolboxes
protected array $tools = [
GeneralInfoTool :: class ,
];
}
When the agent loads, it automatically:
Checks toolbox-level authorization for each toolbox
Filters individual tools based on per-tool gates/policies
Applies any conditional inclusion logic
Merges authorized tools with the agent’s direct tools
You can add or remove toolboxes dynamically at runtime:
Adding/Removing Toolboxes at Runtime
// Add a toolbox based on user tier
if ( $user -> isPremium ()) {
$agent -> addToolbox ( PremiumFeaturesToolbox :: class );
}
// Remove a toolbox if certain conditions aren't met
if ( ! $user -> hasVerifiedEmail ()) {
$agent -> removeToolbox ( SensitiveOperationsToolbox :: class );
}
// Force reload tools after changes
$agent -> forceReloadTools ();
Toolbox Inspection Methods
// Check if a toolbox is registered
if ( $agent -> hasToolbox ( AdminToolbox :: class )) {
// ...
}
// Get all registered toolbox classes
$toolboxClasses = $agent -> getToolboxes ();
// Get loaded toolbox instances (after agent initialization)
$loadedToolboxes = $agent -> getLoadedToolboxes ();
Generate a new toolbox using the Artisan command:
php artisan vizra:make:toolbox CustomerSupportToolbox
You can also specify options during generation:
# With a Laravel Gate
php artisan vizra:make:toolbox AdminToolbox --gate=admin-access
# With a Laravel Policy
php artisan vizra:make:toolbox PremiumToolbox --policy= "App\Policies\SubscriptionPolicy"
# With initial tools
php artisan vizra:make:toolbox OrderToolbox --tools= "App\Tools\CreateOrderTool,App\Tools\CancelOrderTool"
app/Toolboxes/CustomerSupportToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ CreateTicketTool ;
use App\Tools\ SearchKnowledgeBaseTool ;
use App\Tools\ EscalateIssueTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
class CustomerSupportToolbox extends BaseToolbox
{
/**
* The unique identifier for this toolbox.
*/
protected string $name = 'customer_support' ;
/**
* Human-readable description of this toolbox.
*/
protected string $description = 'Tools for customer support operations' ;
/**
* Array of tool class names that belong to this toolbox.
*/
protected array $tools = [
CreateTicketTool :: class ,
SearchKnowledgeBaseTool :: class ,
EscalateIssueTool :: class ,
];
}
Authorization
Toolboxes support a powerful multi-level authorization system using Laravel’s built-in Gates and Policies.
The simplest form of authorization uses a Laravel Gate:
app/Toolboxes/AdminToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ DatabaseQueryTool ;
use App\Tools\ UserManagementTool ;
use App\Tools\ SystemConfigTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
class AdminToolbox extends BaseToolbox
{
protected string $name = 'admin' ;
protected string $description = 'Administrative tools' ;
/**
* Gate name for toolbox-level authorization.
* The entire toolbox is hidden if the gate fails.
*/
protected ? string $gate = 'admin-access' ;
protected array $tools = [
DatabaseQueryTool :: class ,
UserManagementTool :: class ,
SystemConfigTool :: class ,
];
}
Define the gate in your AuthServiceProvider:
app/Providers/AuthServiceProvider.php
use Illuminate\Support\Facades\ Gate ;
public function boot () : void
{
Gate :: define ( 'admin-access' , function ( $user ) {
return $user -> hasRole ( 'admin' );
});
}
For more complex authorization logic, use a Policy:
app/Toolboxes/PremiumToolbox.php
<? php
namespace App\Toolboxes ;
use App\Policies\ SubscriptionPolicy ;
use App\Tools\ AdvancedAnalyticsTool ;
use App\Tools\ BulkExportTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
class PremiumToolbox extends BaseToolbox
{
protected string $name = 'premium' ;
protected string $description = 'Premium tier features' ;
/**
* Policy class for toolbox authorization.
*/
protected ? string $policy = SubscriptionPolicy :: class ;
/**
* The policy ability to check (default is 'use').
*/
protected ? string $policyAbility = 'accessPremiumFeatures' ;
protected array $tools = [
AdvancedAnalyticsTool :: class ,
BulkExportTool :: class ,
];
}
app/Policies/SubscriptionPolicy.php
<? php
namespace App\Policies ;
use App\Models\ User ;
class SubscriptionPolicy
{
public function accessPremiumFeatures ( User $user ) : bool
{
return $user -> subscription ?-> tier === 'premium'
&& $user -> subscription -> isActive ();
}
}
When both a $gate and $policy are defined, the policy takes precedence. Only one authorization method is checked.
You can apply fine-grained authorization to individual tools within a toolbox:
app/Toolboxes/FinanceToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ ViewReportsTool ;
use App\Tools\ CreateInvoiceTool ;
use App\Tools\ ProcessRefundTool ;
use App\Tools\ DeleteTransactionTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
class FinanceToolbox extends BaseToolbox
{
protected string $name = 'finance' ;
protected string $description = 'Financial operations tools' ;
/**
* Toolbox-level gate - user must pass this to see ANY tools.
*/
protected ? string $gate = 'finance-access' ;
protected array $tools = [
ViewReportsTool :: class ,
CreateInvoiceTool :: class ,
ProcessRefundTool :: class ,
DeleteTransactionTool :: class ,
];
/**
* Per-tool gate mappings.
* Users must pass BOTH the toolbox gate AND the tool gate.
*/
protected array $toolGates = [
ProcessRefundTool :: class => 'process-refunds' ,
DeleteTransactionTool :: class => 'delete-transactions' ,
];
}
For even more control, use policies on individual tools:
Per-Tool Policy Configuration
protected array $toolPolicies = [
DeleteTransactionTool :: class => [ TransactionPolicy :: class , 'delete' ],
ArchiveRecordsTool :: class => [ RecordPolicy :: class , 'archive' ],
];
The authorization hierarchy is:
Toolbox gate/policy - Must pass to see any tools
Per-tool gate - Additional check for specific tools
Per-tool policy - Alternative to per-tool gates
shouldIncludeTool() - Final conditional logic
For dynamic logic that goes beyond gates and policies, override the shouldIncludeTool() method:
app/Toolboxes/ContextAwareToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ BasicSearchTool ;
use App\Tools\ AdvancedSearchTool ;
use App\Tools\ BetaFeatureTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
use Vizra\VizraADK\System\ AgentContext ;
class ContextAwareToolbox extends BaseToolbox
{
protected string $name = 'context_aware' ;
protected string $description = 'Tools that adapt to user context' ;
protected array $tools = [
BasicSearchTool :: class ,
AdvancedSearchTool :: class ,
BetaFeatureTool :: class ,
];
/**
* Dynamically include/exclude tools based on context.
*/
protected function shouldIncludeTool ( string $toolClass , AgentContext $context ) : bool
{
// Only include advanced search for power users
if ( $toolClass === AdvancedSearchTool :: class ) {
return $context -> getState ( 'user_tier' ) === 'power_user' ;
}
// Include beta features only for users in the beta program
if ( $toolClass === BetaFeatureTool :: class ) {
return $context -> getState ( 'beta_tester' ) === true ;
}
// Include all other tools by default
return true ;
}
}
Authorized tools are cached per session ID for performance. If context changes mid-session and you need tools to be re-evaluated, call $toolbox->clearCache() or $agent->forceReloadTools().
Real-World Examples
app/Toolboxes/AdminToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ UserManagementTool ;
use App\Tools\ SystemSettingsTool ;
use App\Tools\ ViewAuditLogTool ;
use App\Tools\ DatabaseQueryTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
class AdminToolbox extends BaseToolbox
{
protected string $name = 'admin' ;
protected string $description = 'Administrative tools for system management' ;
protected ? string $gate = 'admin-panel' ;
protected array $tools = [
UserManagementTool :: class ,
SystemSettingsTool :: class ,
ViewAuditLogTool :: class ,
DatabaseQueryTool :: class ,
];
// Restrict dangerous tools to super admins only
protected array $toolGates = [
DatabaseQueryTool :: class => 'database-access' ,
];
}
app/Toolboxes/TenantToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ TenantReportsTool ;
use App\Tools\ TenantSettingsTool ;
use App\Tools\ CrossTenantSearchTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
use Vizra\VizraADK\System\ AgentContext ;
class TenantToolbox extends BaseToolbox
{
protected string $name = 'tenant' ;
protected string $description = 'Multi-tenant management tools' ;
protected array $tools = [
TenantReportsTool :: class ,
TenantSettingsTool :: class ,
CrossTenantSearchTool :: class ,
];
protected function shouldIncludeTool ( string $toolClass , AgentContext $context ) : bool
{
// Cross-tenant search only for users managing multiple tenants
if ( $toolClass === CrossTenantSearchTool :: class ) {
$tenantIds = $context -> getState ( 'managed_tenant_ids' , []);
return count ( $tenantIds ) > 1 ;
}
return true ;
}
}
app/Toolboxes/ExperimentalToolbox.php
<? php
namespace App\Toolboxes ;
use App\Tools\ AiSummaryTool ;
use App\Tools\ VoiceInputTool ;
use App\Tools\ ImageAnalysisTool ;
use Vizra\VizraADK\Toolboxes\ BaseToolbox ;
use Vizra\VizraADK\System\ AgentContext ;
use Illuminate\Support\Facades\ Feature ;
class ExperimentalToolbox extends BaseToolbox
{
protected string $name = 'experimental' ;
protected string $description = 'Experimental features in development' ;
protected array $tools = [
AiSummaryTool :: class ,
VoiceInputTool :: class ,
ImageAnalysisTool :: class ,
];
protected function shouldIncludeTool ( string $toolClass , AgentContext $context ) : bool
{
// Map tool classes to feature flags
$featureFlags = [
AiSummaryTool :: class => 'ai-summary' ,
VoiceInputTool :: class => 'voice-input' ,
ImageAnalysisTool :: class => 'image-analysis' ,
];
$flag = $featureFlags [ $toolClass ] ?? null ;
if ( $flag === null ) {
return true ;
}
// Use Laravel Pennant or similar feature flag system
$userId = $context -> getState ( 'user_id' );
return Feature :: for ( $userId ) -> active ( $flag );
}
}
Best Practices
Group by Domain Organize tools by business domain (orders, payments, support) rather than technical function
Use Gates for Simple Checks Gates are perfect for role-based checks. Use policies for complex business logic
Keep Toolboxes Focused A toolbox should have 3-8 related tools. Split large toolboxes into smaller ones
Prefer Toolbox Auth Use toolbox-level authorization when possible. Per-tool auth adds complexity
Naming Convention : Use descriptive names ending in Toolbox - e.g., CustomerSupportToolbox, PaymentProcessingToolbox, AdminToolbox.
API Reference
Property Type Description $namestringUnique identifier for the toolbox $descriptionstringHuman-readable description $toolsarrayArray of tool class names $gate?stringLaravel Gate name for toolbox auth $policy?stringLaravel Policy class for toolbox auth $policyAbility?stringPolicy ability to check (default: 'use') $toolGatesarrayPer-tool gate mappings $toolPoliciesarrayPer-tool policy mappings
Method Description name(): stringGet the toolbox name description(): stringGet the toolbox description tools(): arrayGet the array of tool class names authorize(AgentContext $context): boolCheck toolbox-level authorization authorizedTools(AgentContext $context): arrayGet instantiated, authorized tools getGate(): ?stringGet the configured gate name getPolicy(): ?stringGet the configured policy class getToolGates(): arrayGet per-tool gate mappings clearCache(): voidClear the authorized tools cache
Method Description addToolbox(string $toolboxClass): staticAdd a toolbox at runtime removeToolbox(string $toolboxClass): staticRemove a toolbox getToolboxes(): arrayGet registered toolbox class names hasToolbox(string $toolboxClass): boolCheck if toolbox is registered getLoadedToolboxes(): arrayGet loaded toolbox instances forceReloadTools(): voidClear cache and reload all tools
Artisan Command
php artisan vizra:make:toolbox {name} [options]
Options:
-g, --gate=GATE Laravel Gate name for authorization
-p, --policy=POLICY Laravel Policy class for authorization
-t, --tools=TOOLS Comma-separated tool class names