M2: agent logic in text mode
- LLMProvider interface: AnthropicLLM + ScriptedLLM test fake - System prompt composition from super-admin template + structured tenant data only (§6.3); auto-generated greetings with recording disclosure, out-of-hours variant, chat variant - Agent tools (§6.5): get_salon_info, check_availability (≤8 slots to model, agent offers ≤3), submit_booking_request (caller-ID fallback, hallucinated service-id guard), take_message - Conversation loop with tool dispatch, round-limit guard, transcript capture, outcome classification (request_created/message_taken/info_only/abandoned) - Terminal playground (python -m gogo.agent.cli) + demo seed (python -m gogo.seed) - Deterministic loop tests (ScriptedLLM) + Appendix A golden-scenario acceptance tests against a real LLM (skipped without an API key) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
58
gogo/agent/cli.py
Normal file
58
gogo/agent/cli.py
Normal file
@@ -0,0 +1,58 @@
|
||||
"""Terminal playground: text conversation with a tenant's agent (M2).
|
||||
|
||||
Usage: python -m gogo.agent.cli salon-merima [--voice]
|
||||
Requires GOGO_ANTHROPIC_API_KEY (or ANTHROPIC_API_KEY via the SDK default).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from sqlalchemy import select
|
||||
|
||||
from gogo.agent.loop import AgentConversation
|
||||
from gogo.db import get_sessionmaker
|
||||
from gogo.models import Tenant
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
args = [a for a in sys.argv[1:] if not a.startswith("--")]
|
||||
slug = args[0] if args else "salon-merima"
|
||||
channel = "voice" if "--voice" in sys.argv else "chat"
|
||||
|
||||
async with get_sessionmaker()() as session:
|
||||
tenant = (
|
||||
await session.execute(select(Tenant).where(Tenant.slug == slug))
|
||||
).scalar_one_or_none()
|
||||
if tenant is None:
|
||||
print(f"tenant '{slug}' not found — run: python -m gogo.seed")
|
||||
sys.exit(1)
|
||||
|
||||
convo = AgentConversation(
|
||||
session,
|
||||
tenant,
|
||||
channel=channel,
|
||||
caller_phone="+38765123456" if channel == "voice" else "",
|
||||
)
|
||||
print(f"[{tenant.name} — {channel} mode, ctrl-d to exit]\n")
|
||||
print(f"Gogo: {await convo.greeting()}\n")
|
||||
|
||||
while True:
|
||||
try:
|
||||
text = input("Vi: ").strip()
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
break
|
||||
if not text:
|
||||
continue
|
||||
reply = await convo.user_turn(text)
|
||||
await session.commit()
|
||||
print(f"\nGogo: {reply}\n")
|
||||
|
||||
print(f"\n[outcome: {convo.outcome}]")
|
||||
for name, tool_input in convo.executor.tool_calls:
|
||||
print(f"[tool] {name}({tool_input})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user