Vision
Kill AgentType. Kill tool registration silos. One flat registry, contexts as the grouping primitive, per-agent policies.
Every tool registers once with a contexts declaration. Resolution is: registry → context filter → agent policy → step policy → global policy → done.
Today the tool system has three separate registration channels (datamachine_global_tools, datamachine_chat_tools, datamachine_system_tools), a ToolManager that manages global enablement, a ToolPolicyResolver that gathers tools per-surface, and an AgentType class that exists but isn't formally connected to any of it. Tools are categorized at registration time — you register a "chat tool" or a "global tool" and that bakes in where it can appear. Chat tools bypass the enablement system entirely.
After this: one tool registry, contexts as the only grouping primitive, one policy evaluation path, and per-agent tool policies.
Implementation Plan
Phase 1: Unified Tool Registry + BaseTool Rewrite
Goal: Single tool registry replacing 3 separate filter channels.
-
Rewrite BaseTool.php:
- Kill
registerGlobalTool() and registerChatTool() methods
- Single
registerTool(string $name, array|callable $definition) method
- Tool definition must include
contexts key (array of strings — extensible, any string valid)
- Single filter:
datamachine_tools replaces datamachine_global_tools + datamachine_chat_tools + datamachine_system_tools
- No backward compat bridge — update all callers directly
-
Rewrite ToolServiceProvider.php:
- All ~46 tools register via single
registerTool() with appropriate contexts
- Current global tools →
contexts: ['chat', 'pipeline', 'standalone']
- Current chat-only tools →
contexts: ['chat']
- No more separate
registerGlobalTools() / registerChatTools() methods
-
Update ability-registered tools (PostQueryAbilities, GetPostBlocksAbility, EditPostBlocksAbility, ReplacePostBlocksAbility):
- Migrate from
registerChatTool() to registerTool() with contexts: ['chat']
Phase 2: Rewrite ToolPolicyResolver + ToolManager
Goal: Context-based resolution replacing surface-based gathering.
Phase 3: Per-Agent Tool Policy
Goal: Agent-level tool scoping stored in agent_config.
-
Schema in agent_config JSON:
{
"tool_policy": {
"mode": "deny",
"tools": ["image_generation", "send_ping"]
}
}
mode: "deny" → agent can use everything EXCEPT listed tools (default if no policy)
mode: "allow" → agent can ONLY use listed tools
- No policy = no restrictions (backward compatible)
-
ToolPolicyResolver reads agent policy when agent_id is provided in context
-
Add agent policy resolution to the pipeline between context filtering and step/global filtering
Phase 4: Delete AgentType + Update All Callers
Goal: Eliminate AgentType as a concept. Contexts replace it.
- Delete
inc/Engine/AI/AgentType.php
- Replace
AgentType::CHAT / AgentType::PIPELINE / AgentType::SYSTEM with string literals 'chat' / 'pipeline' / 'system' everywhere:
ChatOrchestrator.php (~10 references) — pass context: 'chat' + agent_id to resolver
AIStep.php — pass context: 'pipeline' + step_id + agent_id to resolver
Chat.php (database) — change $agent_type parameter to $context, default 'chat'
Chat.php REST API — update parameter name
CreateChatSessionAbility.php — update parameter
AIConversationLoop — receives context string instead of AgentType constant
PluginSettings::getAgentTypes() — rename to getContextTypes() or keep with updated internals
SettingsAbilities.php — update agent_models validation
Providers.php API — update response
ToolExecutor.php deprecated shim — update to use context key
Phase 5: Cleanup + Tests
- Delete dead
datamachine_system_tools filter handling (no production registrations)
- Remove
AgentType references from docs/changelog
- Clean up
ToolExecutor.getAvailableTools() deprecated shim
- Update tests:
ToolPolicyResolverTest — rewrite for context-based API
ChatToolsAvailabilityTest, PipelineToolsAvailabilityTest, WorkspaceToolsAvailabilityTest, WorkspaceScopedToolsTest — update for context-based resolution
AllAbilitiesRegisteredTest — update ability list if needed
- New: per-agent tool policy resolution tests
- Run
homeboy test data-machine — 0 failures
- PHP syntax check all modified files
What Stays Unchanged
ToolExecutor.executeTool() — execution logic unchanged
disabled_tools in pipeline step config — same mechanism, same storage
disabled_tools in global settings — same mechanism
- Handler tools via
chubes_ai_tools filter — pipeline-specific, dynamic, keep as-is
datamachine_resolved_tools filter — final extensibility hook
- Tool definition structure (class, method, description, parameters)
- Chat tool classes stay in
inc/Api/Chat/Tools/ — just registration changes
agent_type column in chat sessions table — values stay the same strings
Related
Vision
Kill AgentType. Kill tool registration silos. One flat registry, contexts as the grouping primitive, per-agent policies.
Every tool registers once with a
contextsdeclaration. Resolution is: registry → context filter → agent policy → step policy → global policy → done.Today the tool system has three separate registration channels (
datamachine_global_tools,datamachine_chat_tools,datamachine_system_tools), a ToolManager that manages global enablement, a ToolPolicyResolver that gathers tools per-surface, and an AgentType class that exists but isn't formally connected to any of it. Tools are categorized at registration time — you register a "chat tool" or a "global tool" and that bakes in where it can appear. Chat tools bypass the enablement system entirely.After this: one tool registry, contexts as the only grouping primitive, one policy evaluation path, and per-agent tool policies.
Implementation Plan
Phase 1: Unified Tool Registry + BaseTool Rewrite
Goal: Single tool registry replacing 3 separate filter channels.
Rewrite
BaseTool.php:registerGlobalTool()andregisterChatTool()methodsregisterTool(string $name, array|callable $definition)methodcontextskey (array of strings — extensible, any string valid)datamachine_toolsreplacesdatamachine_global_tools+datamachine_chat_tools+datamachine_system_toolsRewrite
ToolServiceProvider.php:registerTool()with appropriatecontextscontexts: ['chat', 'pipeline', 'standalone']contexts: ['chat']registerGlobalTools()/registerChatTools()methodsUpdate ability-registered tools (PostQueryAbilities, GetPostBlocksAbility, EditPostBlocksAbility, ReplacePostBlocksAbility):
registerChatTool()toregisterTool()withcontexts: ['chat']Phase 2: Rewrite ToolPolicyResolver + ToolManager
Goal: Context-based resolution replacing surface-based gathering.
Rewrite
ToolPolicyResolver.php:SURFACE_PIPELINE,SURFACE_CHAT, etc.) with context stringsresolve()context keys:context(required),agent_id(optional),step_id(optional),deny,allow_only, plus pipeline-specific keyscontextmatch (tool'scontextsarray contains the requested context)chubes_ai_toolsmechanism)agent_config(Phase 3)disabled_tools(existing)disabled_tools(existing)deny/allow_onlyoverridesdatamachine_resolved_toolsfilterUpdate
ToolManager.php:get_global_tools()→get_all_tools()— returns everything from single registryis_tool_available()simplifies — context filtering handled by resolveris_globally_enabled()stays (reads fromdisabled_toolssetting)get_step_disabled_tools()stays (reads from pipeline step config)Phase 3: Per-Agent Tool Policy
Goal: Agent-level tool scoping stored in
agent_config.Schema in
agent_configJSON:{ "tool_policy": { "mode": "deny", "tools": ["image_generation", "send_ping"] } }mode: "deny"→ agent can use everything EXCEPT listed tools (default if no policy)mode: "allow"→ agent can ONLY use listed toolsToolPolicyResolver reads agent policy when
agent_idis provided in contextAdd agent policy resolution to the pipeline between context filtering and step/global filtering
Phase 4: Delete AgentType + Update All Callers
Goal: Eliminate AgentType as a concept. Contexts replace it.
inc/Engine/AI/AgentType.phpAgentType::CHAT/AgentType::PIPELINE/AgentType::SYSTEMwith string literals'chat'/'pipeline'/'system'everywhere:ChatOrchestrator.php(~10 references) — passcontext: 'chat'+agent_idto resolverAIStep.php— passcontext: 'pipeline'+step_id+agent_idto resolverChat.php(database) — change$agent_typeparameter to$context, default'chat'Chat.phpREST API — update parameter nameCreateChatSessionAbility.php— update parameterAIConversationLoop— receives context string instead of AgentType constantPluginSettings::getAgentTypes()— rename togetContextTypes()or keep with updated internalsSettingsAbilities.php— updateagent_modelsvalidationProviders.phpAPI — update responseToolExecutor.phpdeprecated shim — update to usecontextkeyPhase 5: Cleanup + Tests
datamachine_system_toolsfilter handling (no production registrations)AgentTypereferences from docs/changelogToolExecutor.getAvailableTools()deprecated shimToolPolicyResolverTest— rewrite for context-based APIChatToolsAvailabilityTest,PipelineToolsAvailabilityTest,WorkspaceToolsAvailabilityTest,WorkspaceScopedToolsTest— update for context-based resolutionAllAbilitiesRegisteredTest— update ability list if neededhomeboy test data-machine— 0 failuresWhat Stays Unchanged
ToolExecutor.executeTool()— execution logic unchangeddisabled_toolsin pipeline step config — same mechanism, same storagedisabled_toolsin global settings — same mechanismchubes_ai_toolsfilter — pipeline-specific, dynamic, keep as-isdatamachine_resolved_toolsfilter — final extensibility hookinc/Api/Chat/Tools/— just registration changesagent_typecolumn in chat sessions table — values stay the same stringsRelated