"""One adapter, configured per agent. Both n8n agents get the same image and differ only by environment. That is the point: the A2A surface is identical for every agent in the estate, and what distinguishes the supply agent from the collections agent is the workflow behind the webhook, not the protocol in front of it. Nothing here is a secret. The adapter forwards the end user's token and holds none of its own — the Keycloak client secret belongs to the workflow, stored as an n8n credential, so the component that can mint tokens is the one that uses them. """ from __future__ import annotations from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_prefix="ADAPTER_", env_file=".env") # --- who this instance is ------------------------------------------------ agent_name: str = Field(..., description="e.g. supply") agent_description: str = Field(...) agent_version: str = "0.1.0" # --- the one skill it exposes ------------------------------------------- # One skill per adapter instance, deliberately. An agent that grows a second # skill is an agent whose card should say so explicitly, and reviewing that # is the moment to ask whether it has quietly become a data proxy. skill_id: str = Field(..., description="e.g. check_availability") skill_name: str = Field(...) skill_description: str = Field(...) skill_examples: str = "" """Newline-separated. They go in the card, which is what a calling agent's model reads to decide whether this is the specialist to ask.""" # --- the workflow behind it --------------------------------------------- webhook_url: str = Field(..., description="the n8n Webhook node's production URL") # A workflow is not a chat: it runs rules, calls APIs, and may wait on a # slow backend. The default here is generous for that, not for a model. webhook_timeout: float = 120.0 # --- transport ----------------------------------------------------------- ca_bundle: str | None = None host: str = "0.0.0.0" port: int = 8080 public_url: str = "http://localhost:8080/" @property def verify(self) -> str | bool: return self.ca_bundle if self.ca_bundle else True @property def examples(self) -> list[str]: return [line.strip() for line in self.skill_examples.splitlines() if line.strip()]