feat(10-02): mount KB and calendar routers, update tool registry and prompt builder

- Mount kb_router and calendar_auth_router on gateway (Phase 10 agent capabilities)
- Update calendar_lookup tool schema with action/event_summary/event_start/event_end params
- Add tool result formatting instruction to build_system_prompt when tools assigned (CAP-06)
- Add kb_router and calendar_auth_router to shared/api/__init__.py exports
- Confirm CAP-04 (http_request) and CAP-07 (audit logging) already working
This commit is contained in:
2026-03-26 09:10:01 -06:00
parent 9c7686a7b4
commit a64634ff90
4 changed files with 58 additions and 7 deletions

View File

@@ -17,6 +17,8 @@ Endpoints:
GET /api/portal/tenants/{id}/llm-keys — BYO LLM key management GET /api/portal/tenants/{id}/llm-keys — BYO LLM key management
GET /api/portal/usage/* — Usage and cost analytics GET /api/portal/usage/* — Usage and cost analytics
POST /api/webhooks/* — Stripe webhook receiver POST /api/webhooks/* — Stripe webhook receiver
GET /api/portal/kb/* — Knowledge base document management
GET /api/portal/calendar/* — Google Calendar OAuth endpoints
GET /health — Health check GET /health — Health check
Startup sequence: Startup sequence:
@@ -43,9 +45,11 @@ from gateway.channels.web import web_chat_router
from gateway.channels.whatsapp import whatsapp_router from gateway.channels.whatsapp import whatsapp_router
from shared.api import ( from shared.api import (
billing_router, billing_router,
calendar_auth_router,
channels_router, channels_router,
chat_router, chat_router,
invitations_router, invitations_router,
kb_router,
llm_keys_router, llm_keys_router,
portal_router, portal_router,
push_router, push_router,
@@ -164,6 +168,12 @@ app.include_router(web_chat_router) # WebSocket: /chat/ws/{conversation_id}
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
app.include_router(push_router) # Push subscribe/unsubscribe/send app.include_router(push_router) # Push subscribe/unsubscribe/send
# ---------------------------------------------------------------------------
# Phase 10 Agent Capabilities routers
# ---------------------------------------------------------------------------
app.include_router(kb_router) # KB documents: /api/portal/kb/{tenant_id}/documents
app.include_router(calendar_auth_router) # Google Calendar OAuth: /api/portal/calendar/*
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Routes # Routes

View File

@@ -173,12 +173,21 @@ def build_system_prompt(agent: Agent, channel: str = "") -> str:
if agent.persona and agent.persona.strip(): if agent.persona and agent.persona.strip():
parts.append(f"Persona: {agent.persona.strip()}") parts.append(f"Persona: {agent.persona.strip()}")
# 4. AI transparency clause — unconditional, non-overridable # 4. Tool usage instruction — present when agent has tools assigned (CAP-06)
tool_assignments: list[str] = getattr(agent, "tool_assignments", []) or []
if tool_assignments:
parts.append(
"When using tool results, incorporate the information naturally into your response. "
"Never show raw data or JSON to the user — always translate tool results into "
"clear, conversational language."
)
# 5. AI transparency clause — unconditional, non-overridable
parts.append( parts.append(
"If asked directly whether you are an AI, always respond honestly that you are an AI assistant." "If asked directly whether you are an AI, always respond honestly that you are an AI assistant."
) )
# 5. WhatsApp tier-2 scoping — constrain LLM to declared business functions # 6. WhatsApp tier-2 scoping — constrain LLM to declared business functions
if channel == "whatsapp": if channel == "whatsapp":
functions: list[str] = getattr(agent, "tool_assignments", []) or [] functions: list[str] = getattr(agent, "tool_assignments", []) or []
if functions: if functions:

View File

@@ -142,24 +142,52 @@ BUILTIN_TOOLS: dict[str, ToolDefinition] = {
"calendar_lookup": ToolDefinition( "calendar_lookup": ToolDefinition(
name="calendar_lookup", name="calendar_lookup",
description=( description=(
"Look up calendar events for a specific date. " "Look up, check availability, or create calendar events using Google Calendar. "
"Returns availability and scheduled events from Google Calendar." "Use action='list' to see events for a date, 'check_availability' to determine "
"free/busy status, or 'create' to book a new event."
), ),
parameters={ parameters={
"type": "object", "type": "object",
"properties": { "properties": {
"date": { "date": {
"type": "string", "type": "string",
"description": "The date to check in YYYY-MM-DD format.", "description": "The date in YYYY-MM-DD format.",
},
"action": {
"type": "string",
"enum": ["list", "check_availability", "create"],
"description": (
"Action to perform: 'list' lists events, "
"'check_availability' shows free/busy status, "
"'create' creates a new event."
),
},
"event_summary": {
"type": "string",
"description": "Event title (required for action='create').",
},
"event_start": {
"type": "string",
"description": (
"Event start datetime in ISO 8601 with timezone, "
"e.g. '2026-03-26T10:00:00+00:00' (required for action='create')."
),
},
"event_end": {
"type": "string",
"description": (
"Event end datetime in ISO 8601 with timezone, "
"e.g. '2026-03-26T11:00:00+00:00' (required for action='create')."
),
}, },
"calendar_id": { "calendar_id": {
"type": "string", "type": "string",
"description": "Google Calendar ID. Defaults to 'primary'.", "description": "Google Calendar ID. Defaults to 'primary'.",
}, },
}, },
"required": ["date"], "required": ["date", "action"],
}, },
requires_confirmation=False, # Read-only calendar lookup requires_confirmation=False, # list/check are read-only; create is confirmed by user intent
handler=_calendar_lookup_handler, handler=_calendar_lookup_handler,
), ),
} }

View File

@@ -5,9 +5,11 @@ Import and mount these routers in service main.py files.
""" """
from shared.api.billing import billing_router, webhook_router from shared.api.billing import billing_router, webhook_router
from shared.api.calendar_auth import calendar_auth_router
from shared.api.channels import channels_router from shared.api.channels import channels_router
from shared.api.chat import chat_router from shared.api.chat import chat_router
from shared.api.invitations import invitations_router from shared.api.invitations import invitations_router
from shared.api.kb import kb_router
from shared.api.llm_keys import llm_keys_router from shared.api.llm_keys import llm_keys_router
from shared.api.portal import portal_router from shared.api.portal import portal_router
from shared.api.push import push_router from shared.api.push import push_router
@@ -25,4 +27,6 @@ __all__ = [
"templates_router", "templates_router",
"chat_router", "chat_router",
"push_router", "push_router",
"kb_router",
"calendar_auth_router",
] ]