3.3: Modify Agent and ToolRegistry for multi-agent
Agent changes: - Accept optional AgentConfig in __init__ - Add name property - Filter tools via agent_config.tools whitelist in respond() - Use agent-specific personality file when configured - Pass agent name to skills registry for filtering ToolRegistry changes: - get_tools_schema() accepts filter_names parameter - get_tools_description() accepts filter_names parameter - When filter_names is None, all tools are returned (backward compat) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>cora-start
parent
537e3bd528
commit
86511d5a0f
|
|
@ -9,7 +9,7 @@ import uuid
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .config import Config
|
from .config import AgentConfig, Config
|
||||||
from .db import Database
|
from .db import Database
|
||||||
from .llm import LLMAdapter
|
from .llm import LLMAdapter
|
||||||
from .router import build_system_prompt, format_messages_for_llm
|
from .router import build_system_prompt, format_messages_for_llm
|
||||||
|
|
@ -63,15 +63,26 @@ def _build_file_content_parts(files: list[str]) -> list[dict]:
|
||||||
|
|
||||||
|
|
||||||
class Agent:
|
class Agent:
|
||||||
def __init__(self, config: Config, db: Database, llm: LLMAdapter):
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: Config,
|
||||||
|
db: Database,
|
||||||
|
llm: LLMAdapter,
|
||||||
|
agent_config: AgentConfig | None = None,
|
||||||
|
):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.db = db
|
self.db = db
|
||||||
self.llm = llm
|
self.llm = llm
|
||||||
|
self.agent_config = agent_config or AgentConfig()
|
||||||
self.conv_id: str | None = None
|
self.conv_id: str | None = None
|
||||||
self._memory = None # set by app after memory system init
|
self._memory = None # set by app after memory system init
|
||||||
self._tools = None # set by app after tool system init
|
self._tools = None # set by app after tool system init
|
||||||
self._skills_registry = None # set by app after skills init
|
self._skills_registry = None # set by app after skills init
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self.agent_config.name
|
||||||
|
|
||||||
def set_memory(self, memory):
|
def set_memory(self, memory):
|
||||||
self._memory = memory
|
self._memory = memory
|
||||||
|
|
||||||
|
|
@ -104,18 +115,29 @@ class Agent:
|
||||||
if self._memory:
|
if self._memory:
|
||||||
memory_context = self._memory.get_context(user_input)
|
memory_context = self._memory.get_context(user_input)
|
||||||
|
|
||||||
|
# Apply tool whitelist from agent config
|
||||||
|
tool_filter = self.agent_config.tools
|
||||||
|
|
||||||
tools_schema = []
|
tools_schema = []
|
||||||
tools_description = ""
|
tools_description = ""
|
||||||
if self._tools:
|
if self._tools:
|
||||||
tools_schema = self._tools.get_tools_schema()
|
tools_schema = self._tools.get_tools_schema(filter_names=tool_filter)
|
||||||
tools_description = self._tools.get_tools_description()
|
tools_description = self._tools.get_tools_description(filter_names=tool_filter)
|
||||||
|
|
||||||
skills_context = ""
|
skills_context = ""
|
||||||
if self._skills_registry:
|
if self._skills_registry:
|
||||||
skills_context = self._skills_registry.get_prompt_section()
|
skills_context = self._skills_registry.get_prompt_section(self.name)
|
||||||
|
|
||||||
|
# Use agent-specific personality file if configured
|
||||||
|
identity_dir = self.config.identity_dir
|
||||||
|
personality_file = self.agent_config.personality_file
|
||||||
|
if personality_file:
|
||||||
|
pf = Path(personality_file)
|
||||||
|
if pf.exists():
|
||||||
|
identity_dir = pf.parent
|
||||||
|
|
||||||
system_prompt = build_system_prompt(
|
system_prompt = build_system_prompt(
|
||||||
identity_dir=self.config.identity_dir,
|
identity_dir=identity_dir,
|
||||||
memory_context=memory_context,
|
memory_context=memory_context,
|
||||||
tools_description=tools_description,
|
tools_description=tools_description,
|
||||||
skills_context=skills_context,
|
skills_context=skills_context,
|
||||||
|
|
|
||||||
|
|
@ -118,15 +118,20 @@ class ToolRegistry:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.warning("Failed to load tool module %s: %s", module_name, e)
|
log.warning("Failed to load tool module %s: %s", module_name, e)
|
||||||
|
|
||||||
def get_tools_schema(self) -> list[dict]:
|
def get_tools_schema(self, filter_names: list[str] | None = None) -> list[dict]:
|
||||||
"""Get all tools in OpenAI function-calling format."""
|
"""Get tools in OpenAI function-calling format, optionally filtered."""
|
||||||
return [t.to_openai_schema() for t in _TOOLS.values()]
|
tools = _TOOLS.values()
|
||||||
|
if filter_names is not None:
|
||||||
|
tools = [t for t in tools if t.name in filter_names]
|
||||||
|
return [t.to_openai_schema() for t in tools]
|
||||||
|
|
||||||
def get_tools_description(self) -> str:
|
def get_tools_description(self, filter_names: list[str] | None = None) -> str:
|
||||||
"""Human-readable tool list for system prompt."""
|
"""Human-readable tool list for system prompt, optionally filtered."""
|
||||||
lines = []
|
lines = []
|
||||||
by_cat: dict[str, list[ToolDef]] = {}
|
by_cat: dict[str, list[ToolDef]] = {}
|
||||||
for t in _TOOLS.values():
|
for t in _TOOLS.values():
|
||||||
|
if filter_names is not None and t.name not in filter_names:
|
||||||
|
continue
|
||||||
by_cat.setdefault(t.category, []).append(t)
|
by_cat.setdefault(t.category, []).append(t)
|
||||||
|
|
||||||
for cat, tools in sorted(by_cat.items()):
|
for cat, tools in sorted(by_cat.items()):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue