Files
agentic-codemod-pipeline/src/agentic_codemod/apm/agno_bridge.py
T
2026-08-29 13:17:59 +02:00

89 lines
3.2 KiB
Python

"""Kompilacja prymitywów APM do obiektów agno.
To jest sedno rozwiązania: definicja agenta (rola, model, narzędzia, skille, schemat wyjścia)
jest wersjonowanym artefaktem APM, a nie kodem. Zmiana zachowania sieci agentowej
nie wymaga zmiany Pythona - wymaga podbicia wersji pakietu kontekstowego.
"""
from __future__ import annotations
from collections.abc import Callable
from typing import Any
from agno.agent import Agent
from agno.skills import LocalSkills, Skills
from ..config import Settings
from ..llm import ModelFactory
from .loader import ApmContext
from .primitives import AgentPrimitive
class ToolResolutionError(RuntimeError):
pass
def _resolve_tools(names: list[str], registry: dict[str, Callable[..., Any]]) -> list[Callable[..., Any]]:
unknown = [n for n in names if n not in registry]
if unknown:
raise ToolResolutionError(
f"Definicja agenta odwołuje się do nieistniejących narzędzi: {', '.join(unknown)}. "
f"Dostępne: {', '.join(sorted(registry))}"
)
return [registry[n] for n in names]
def build_skills(ctx: ApmContext, names: list[str]) -> Skills | None:
"""Buduje natywny obiekt `Skills` agno z katalogów skilli dostarczonych przez APM.
agno waliduje katalogi względem specyfikacji Agent Skills - niepoprawny skill
wysadza przebieg na starcie, a nie w połowie modyfikacji kodu.
"""
if not names:
return None
paths = ctx.skill_paths(names)
return Skills(loaders=[LocalSkills(str(p)) for p in paths])
def build_agent(
definition: AgentPrimitive,
ctx: ApmContext,
settings: Settings,
model_factory: ModelFactory,
tool_registry: dict[str, Callable[..., Any]],
schema_registry: dict[str, type] | None = None,
) -> Agent:
schema_registry = schema_registry or {}
instructions: list[str] = []
instructions.extend(ctx.context_bodies(definition.context_names))
instructions.append(definition.body)
instructions.extend(ctx.instruction_bodies(definition.instruction_names))
output_schema = None
if definition.output_schema_name:
if definition.output_schema_name not in schema_registry:
raise KeyError(
f"Agent '{definition.name}' deklaruje output_schema='{definition.output_schema_name}', "
f"którego nie ma w rejestrze schematów: {sorted(schema_registry)}"
)
output_schema = schema_registry[definition.output_schema_name]
return Agent(
name=definition.name,
description=definition.description or None,
model=model_factory.for_profile(definition.model_profile, definition.temperature),
instructions=instructions,
tools=_resolve_tools(definition.tool_names, tool_registry) or None,
skills=build_skills(ctx, definition.skill_names),
output_schema=output_schema,
tool_call_limit=definition.tool_call_limit or settings.tool_call_limit,
markdown=False,
telemetry=False,
add_datetime_to_context=True,
# Nazwa roli w kontekście systemowym: pomaga modelowi trzymać się swojego zadania,
# a atrapie LLM (llm/mock_server.py) rozpoznać, który agent pyta.
add_name_to_context=True,
retries=2,
)