From 922d7f1b50b6dc1434f13592807b5eaaa3c67863 Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Wed, 21 Oct 2026 09:47:31 -0300 Subject: [PATCH] Adjustments for /oracle organization --- apps/agent_gateway/app/main.py | 4 +- apps/agent_gateway/app/settings.py | 7 ++ apps/agent_gateway/app/supervisor_llm.py | 102 ++++++++++++++++++++ apps/agent_gateway/config/llm_profiles.yaml | 93 ++++++++++++++++++ docs/A2A_IMPLEMENTACAO.md | 2 +- 5 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 apps/agent_gateway/app/supervisor_llm.py create mode 100644 apps/agent_gateway/config/llm_profiles.yaml diff --git a/apps/agent_gateway/app/main.py b/apps/agent_gateway/app/main.py index 9556ba7e..8790058b 100644 --- a/apps/agent_gateway/app/main.py +++ b/apps/agent_gateway/app/main.py @@ -16,7 +16,7 @@ from agent_framework.global_supervisor import ( GlobalSupervisorRouter, InMemoryGlobalSessionStore, ) -from agent_framework.llm.providers import create_llm +from app.supervisor_llm import build_supervisor_llm from agent_framework.observability.observer import AgentObserver from agent_framework.security import install_authentication @@ -38,7 +38,7 @@ app.add_middleware( registry = BackendRegistry.from_yaml(settings.BACKENDS_CONFIG_PATH) analytics = create_analytics_publisher(settings) observer = AgentObserver(analytics=analytics) -llm = create_llm(settings) +llm = build_supervisor_llm(settings) if settings.GLOBAL_ROUTING_MODE in {"supervisor", "hybrid"} else None session_store = InMemoryGlobalSessionStore(ttl_seconds=settings.GLOBAL_SESSION_TTL_SECONDS) router = GlobalSupervisorRouter( registry=registry, diff --git a/apps/agent_gateway/app/settings.py b/apps/agent_gateway/app/settings.py index 77957e73..f6fc8ff3 100644 --- a/apps/agent_gateway/app/settings.py +++ b/apps/agent_gateway/app/settings.py @@ -46,6 +46,13 @@ class GatewaySettings(BaseSettings): LANGFUSE_HOST: str = "https://cloud.langfuse.com" MODEL_PRICES_JSON: str | None = None USD_BRL_RATE: str = "5.0" + OCI_COMPARTMENT_ID: str | None = None + OCI_GENAI_PROJECT_OCID: str | None = None + + OCI_AUTH_MODE: str = "config_file" + OCI_CONFIG_FILE: str = "~/.oci/config" + OCI_CONFIG_PROFILE: str = "DEFAULT" + OCI_REGION: str | None = None # Analytics/Observer do próprio gateway. ENABLE_ANALYTICS: bool = False diff --git a/apps/agent_gateway/app/supervisor_llm.py b/apps/agent_gateway/app/supervisor_llm.py new file mode 100644 index 00000000..7a84b7d0 --- /dev/null +++ b/apps/agent_gateway/app/supervisor_llm.py @@ -0,0 +1,102 @@ +"""Gateway-only bootstrap for the Global Supervisor LLM. + +Resolve the supervisor entry in llm_profiles.yaml *before* create_llm(). +This matters because create_llm() selects OCISDKProvider immediately when +LLM_PROVIDER=oci_sdk; OCISDKProvider does not dynamically switch providers. +""" +from __future__ import annotations + +import logging +import os +from pathlib import Path + +import yaml + +from agent_framework.llm.providers import create_llm + +logger = logging.getLogger("agent_gateway.supervisor_llm") + + +def _profile_file(settings) -> Path: + explicit = ( + os.getenv("GLOBAL_SUPERVISOR_LLM_PROFILES_PATH") + or getattr(settings, "GLOBAL_SUPERVISOR_LLM_PROFILES_PATH", None) + or os.getenv("LLM_PROFILES_PATH") + or getattr(settings, "LLM_PROFILES_PATH", None) + ) + if explicit: + path = Path(str(explicit)).expanduser().resolve() + if not path.is_file(): + raise RuntimeError(f"Supervisor LLM profile YAML not found: {path}") + return path + + candidates = ( + "config/llm_profiles.yaml", + "llm_profiles.yaml", + "apps/agent_gateway/config/llm_profiles.yaml", + "apps/agent_template_backend/config/llm_profiles.yaml", + "apps/agent_template_backend/llm_profiles.yaml", + ) + for candidate in candidates: + path = Path(candidate) + if path.is_file(): + return path.resolve() + raise RuntimeError( + "No llm_profiles.yaml found for Gateway supervisor. Set " + "GLOBAL_SUPERVISOR_LLM_PROFILES_PATH to the EXISTING YAML file path." + ) + + +def build_supervisor_llm(settings): + """Create LLM from the supervisor profile without mutating global settings.""" + path = _profile_file(settings) + data = yaml.safe_load(path.read_text(encoding="utf-8")) or {} + profile = (data.get("profiles") or {}).get("supervisor") + if not isinstance(profile, dict): + raise RuntimeError(f"Missing profiles.supervisor in {path}") + + effective_provider = str(profile.get("provider") or settings.LLM_PROVIDER).strip() + allowed = {"oci_openai", "openai_compatible", "oci_sdk", "mock"} + if effective_provider not in allowed: + raise RuntimeError(f"Unsupported supervisor provider: {effective_provider}") + + configured_url = ( + profile.get("base_url") + or profile.get("service_endpoint") + or getattr(settings, "OCI_GENAI_BASE_URL", None) + ) + url = str(configured_url or "").strip().rstrip("/") + if effective_provider == "oci_openai": + # OCI native URL is commonly used by the process-wide .env when the + # default provider is oci_sdk. Translate only the well-known OCI host. + if url.startswith("https://inference.generativeai.") and url.endswith(".oci.oraclecloud.com"): + url += "/openai/v1" + if not url.endswith("/openai/v1"): + raise RuntimeError( + f"Supervisor OpenAI-compatible base URL must end with /openai/v1, got {url!r}. " + "Set base_url under profiles.supervisor to the working endpoint." + ) + + key = profile.get("api_key") or getattr(settings, "OCI_GENAI_API_KEY", None) or os.getenv("OCI_GENAI_API_KEY") + if effective_provider in {"oci_openai", "openai_compatible"} and not key: + raise RuntimeError( + "Supervisor profile requires OCI_GENAI_API_KEY (or profiles.supervisor.api_key). " + "OCI SDK config_file signing is NOT an OpenAI-compatible bearer API key." + ) + + overrides = { + "LLM_PROVIDER": effective_provider, + "OCI_GENAI_MODEL": str(profile.get("model") or settings.OCI_GENAI_MODEL), + "OCI_GENAI_BASE_URL": url, + "LLM_TEMPERATURE": float(profile.get("temperature", settings.LLM_TEMPERATURE)), + "LLM_MAX_TOKENS": int(profile.get("max_tokens", settings.LLM_MAX_TOKENS)), + } + if key: + overrides["OCI_GENAI_API_KEY"] = str(key) + + supervisor_settings = settings.model_copy(update=overrides) + logger.info( + "Supervisor LLM profile loaded path=%s provider=%s model=%s base_url=%s", + path, effective_provider, overrides["OCI_GENAI_MODEL"], url, + ) + return create_llm(supervisor_settings) diff --git a/apps/agent_gateway/config/llm_profiles.yaml b/apps/agent_gateway/config/llm_profiles.yaml new file mode 100644 index 00000000..93e04010 --- /dev/null +++ b/apps/agent_gateway/config/llm_profiles.yaml @@ -0,0 +1,93 @@ +profiles: + default: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.2 + max_tokens: 2048 + supervisor: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 700 + route_continuity: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 80 + timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 + router: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 768 + guardrail: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 600 + grl: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 700 + judge: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 800 + rag_rewriter: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 300 + rag_compressor: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 1200 + rag_generation: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.1 + max_tokens: 1800 + summary_memory: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.1 + max_tokens: 1200 + noc: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0 + max_tokens: 700 + billing_agent: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.2 + product_agent: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.2 + backoffice_agent: + provider: oci_openai + model: openai.gpt-4.1 + temperature: 0.2 + mcp_parameter_extraction: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 80 + timeout_seconds: 5 + + transaction_parameter_extraction: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 500 + timeout_seconds: 8 diff --git a/docs/A2A_IMPLEMENTACAO.md b/docs/A2A_IMPLEMENTACAO.md index d96b3eec..4c2e1d19 100644 --- a/docs/A2A_IMPLEMENTACAO.md +++ b/docs/A2A_IMPLEMENTACAO.md @@ -29,7 +29,7 @@ python -m pip install -e 'libs/agent_framework[a2a]' -r apps/agent_gateway/requi export ENABLE_A2A=true export A2A_PUBLIC_URL=https://meu-gateway.example export BACKENDS_CONFIG_PATH="$PWD/apps/agent_gateway/config/backends.a2a.example.yaml" -python -m uvicorn app.main:app --app-dir apps/agent_gateway --port 8010 +python -m uvicorn app.main:app --app-dir apps/agent_gateway --env-file .env --port 8010 ``` Edite primeiro as URLs do catálogo de exemplo. Para agentes externos, informe o