bc83df3ed0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
58 lines
2.4 KiB
Python
58 lines
2.4 KiB
Python
"""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()]
|