refactor(block-h): own integration agent tools in their plugins

This commit is contained in:
Agent Zero
2026-08-23 11:44:14 +02:00
parent 637cfa7940
commit 1f4a621910
2 changed files with 188 additions and 4 deletions
+98 -4
View File
@@ -210,12 +210,11 @@ class AutomationPlugin(BasePlugin):
register_agent_coordinator_tools() register_agent_coordinator_tools()
except Exception: except Exception:
logger.exception("Failed to register agent coordinator tools") logger.exception("Failed to register agent coordinator tools")
# Register integration tools (I-AW: Agent→Workflow, I-AK: Agent→Knowledge) # Register workflow agent tools (I-AW: Agent→Workflow)
try: try:
from app.ai.integration_tools import register_integration_tools self._register_workflow_agent_tools()
register_integration_tools()
except Exception: except Exception:
logger.exception("Failed to register integration tools") logger.exception("Failed to register workflow agent tools")
# Register MiniApps from manifest # Register MiniApps from manifest
try: try:
from app.plugins.builtins.kommunikation.contracts import get_miniapp_registry from app.plugins.builtins.kommunikation.contracts import get_miniapp_registry
@@ -286,6 +285,94 @@ class AutomationPlugin(BasePlugin):
logger.info("Automation plugin activated") logger.info("Automation plugin activated")
def _register_workflow_agent_tools(self) -> None:
"""Register I-AW agent tools for starting and inspecting workflows."""
import uuid
from typing import Any
from app.ai.tool_registry import get_tool_registry
registry = get_tool_registry()
async def _start_workflow_handler(arguments: dict[str, Any], context: dict[str, Any]) -> dict[str, Any]:
"""Start a workflow by ID."""
from app.services.workflow_service import create_instance
from app.core.db import get_worker_session_factory
workflow_id = arguments.get("workflow_id", "")
tenant_id = context.get("tenant_id")
user_id = context.get("user_id")
if not workflow_id or not tenant_id:
return {"error": "workflow_id and tenant_id required"}
factory = get_worker_session_factory()
async with factory() as db:
instance = await create_instance(
db=db,
tenant_id=uuid.UUID(str(tenant_id)),
workflow_id=uuid.UUID(workflow_id),
initiated_by=uuid.UUID(str(user_id)) if user_id else None,
)
await db.commit()
return {"instance_id": str(instance.get("id", "")), "status": instance.get("status", "created")}
registry.register(
name="start_workflow",
description="Start a workflow by its ID. Returns the instance ID and status.",
parameters={
"type": "object",
"properties": {
"workflow_id": {"type": "string", "description": "UUID of the workflow to start"},
},
"required": ["workflow_id"],
},
handler=_start_workflow_handler,
plugin_name=self.manifest.name,
required_permission="workflows:read",
category="workflow",
)
async def _check_workflow_status_handler(arguments: dict[str, Any], context: dict[str, Any]) -> dict[str, Any]:
"""Check the status of a workflow instance."""
from sqlalchemy import select
from app.models.workflow import WorkflowInstance
from app.core.db import get_worker_session_factory
instance_id = arguments.get("instance_id", "")
tenant_id = context.get("tenant_id")
if not instance_id or not tenant_id:
return {"error": "instance_id and tenant_id required"}
factory = get_worker_session_factory()
async with factory() as db:
result = await db.execute(
select(WorkflowInstance).where(
WorkflowInstance.id == uuid.UUID(instance_id),
WorkflowInstance.tenant_id == uuid.UUID(str(tenant_id)),
)
)
inst = result.scalar_one_or_none()
if not inst:
return {"error": "Instance not found"}
return {
"instance_id": str(inst.id),
"status": inst.status,
"current_step": inst.current_step_index,
"completed_at": inst.completed_at.isoformat() if inst.completed_at else None,
}
registry.register(
name="check_workflow_status",
description="Check the status of a workflow instance by its ID.",
parameters={
"type": "object",
"properties": {
"instance_id": {"type": "string", "description": "UUID of the workflow instance"},
},
"required": ["instance_id"],
},
handler=_check_workflow_status_handler,
plugin_name=self.manifest.name,
required_permission="workflows:read",
category="workflow",
)
logger.info("Registered workflow agent tools: start_workflow, check_workflow_status")
async def on_deactivate(self, db, service_container, event_bus) -> None: async def on_deactivate(self, db, service_container, event_bus) -> None:
"""Clean up on deactivation.""" """Clean up on deactivation."""
# Contract abmelden # Contract abmelden
@@ -307,6 +394,13 @@ class AutomationPlugin(BasePlugin):
unregister_agent_coordinator_tools() unregister_agent_coordinator_tools()
except Exception: except Exception:
logger.exception("Failed to unregister agent coordinator tools") logger.exception("Failed to unregister agent coordinator tools")
# Unregister workflow agent tools from the core AI tool registry
try:
from app.ai.tool_registry import get_tool_registry
get_tool_registry().unregister_plugin(self.manifest.name)
logger.info("Unregistered AI agent tools for plugin '%s'", self.manifest.name)
except Exception:
logger.exception("Failed to unregister AI agent tools")
# Unregister MiniApps # Unregister MiniApps
try: try:
from app.plugins.builtins.kommunikation.contracts import get_miniapp_registry from app.plugins.builtins.kommunikation.contracts import get_miniapp_registry
+90
View File
@@ -1,6 +1,8 @@
"""Knowledge plugin — LLM-based entity/relationship extraction, ask-knowledge, review queue.""" """Knowledge plugin — LLM-based entity/relationship extraction, ask-knowledge, review queue."""
from __future__ import annotations from __future__ import annotations
import logging import logging
import uuid
from typing import Any
from app.plugins.base import BasePlugin from app.plugins.base import BasePlugin
from app.plugins.manifest import PluginManifest, PluginRouteDef from app.plugins.manifest import PluginManifest, PluginRouteDef
@@ -59,9 +61,97 @@ class KnowledgePlugin(BasePlugin):
logger.info("Registered knowledge extraction hooks") logger.info("Registered knowledge extraction hooks")
except Exception: except Exception:
logger.exception("Failed to register knowledge hooks") logger.exception("Failed to register knowledge hooks")
# Register knowledge agent tools (I-AK: Agent→Knowledge)
try:
self._register_knowledge_agent_tools()
except Exception:
logger.exception("Failed to register knowledge agent tools")
def _register_knowledge_agent_tools(self) -> None:
"""Register I-AK agent tools for asking and searching knowledge."""
from app.ai.tool_registry import get_tool_registry
registry = get_tool_registry()
async def _ask_knowledge_handler(arguments: dict[str, Any], context: dict[str, Any]) -> dict[str, Any]:
"""Ask a knowledge question."""
from app.plugins.builtins.knowledge.services import ask_knowledge
from app.core.db import get_worker_session_factory
question = arguments.get("question", "")
tenant_id = context.get("tenant_id")
if not question or not tenant_id:
return {"error": "question and tenant_id required"}
factory = get_worker_session_factory()
async with factory() as db:
result = await ask_knowledge(db=db, tenant_id=uuid.UUID(str(tenant_id)), question=question)
return {"answer": result.get("answer", ""), "evidence_count": len(result.get("evidence", []))}
registry.register(
name="ask_knowledge",
description="Ask a knowledge question. Searches wiki articles and graph relationships for context.",
parameters={
"type": "object",
"properties": {
"question": {"type": "string", "description": "The question to ask"},
},
"required": ["question"],
},
handler=_ask_knowledge_handler,
plugin_name=self.manifest.name,
required_permission="wiki:read",
category="knowledge",
)
async def _search_knowledge_handler(arguments: dict[str, Any], context: dict[str, Any]) -> dict[str, Any]:
"""Search wiki articles via unified search."""
from app.plugins.builtins.unified_search.provider_registry import get_search_registry
from app.core.db import get_worker_session_factory
query = arguments.get("query", "")
tenant_id = context.get("tenant_id")
if not query or not tenant_id:
return {"error": "query and tenant_id required"}
factory = get_worker_session_factory()
async with factory() as db:
search_registry = get_search_registry()
wiki_provider = search_registry.get("wiki_article")
if not wiki_provider:
return {"error": "Wiki search provider not available"}
results = await wiki_provider._search_fts_filtered(
db=db, tsquery=query, tenant_id=uuid.UUID(str(tenant_id)), limit=5, visible_ids=None
)
return {
"results": [
{"title": r.get("title", ""), "summary": (r.get("summary") or r.get("content", "")[:200] or "")}
for r in results
],
"count": len(results),
}
registry.register(
name="search_knowledge",
description="Search wiki articles by keyword. Returns matching articles with title and summary.",
parameters={
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"},
},
"required": ["query"],
},
handler=_search_knowledge_handler,
plugin_name=self.manifest.name,
required_permission="wiki:read",
category="knowledge",
)
logger.info("Registered knowledge agent tools: ask_knowledge, search_knowledge")
async def on_deactivate(self, db, service_container, event_bus) -> None: async def on_deactivate(self, db, service_container, event_bus) -> None:
"""Clean up on deactivation.""" """Clean up on deactivation."""
from app.core.hooks import unregister_actions_by_owner from app.core.hooks import unregister_actions_by_owner
unregister_actions_by_owner("knowledge") unregister_actions_by_owner("knowledge")
# Unregister knowledge agent tools from the core AI tool registry
try:
from app.ai.tool_registry import get_tool_registry
get_tool_registry().unregister_plugin(self.manifest.name)
logger.info("Unregistered AI agent tools for plugin '%s'", self.manifest.name)
except Exception:
logger.exception("Failed to unregister AI agent tools")
await super().on_deactivate(db, service_container, event_bus) await super().on_deactivate(db, service_container, event_bus)