trtc-ai-service — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited trtc-ai-service (Agent Skill) and scored it 65/100 (yellow). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 10 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 10 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
A bulleted imperative like {match} tells the agent to never reveal, disclose, or mention something to the user. Used adversarially it can instruct the agent to hide its tool calls or lie about what it did — stripping the transparency a user relies on to trust the agent.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This document is the Coding Agent's execution SOP. It also serves as a user-friendly guide reference. For any natural-language intent involving "build / integrate AI customer service," the AI must read this file first before taking action. All script calls must strictly follow §10 Tool Whitelist.
All runtime assets of this Skill (capabilities/, scripts/, scenarios/, auto_adapters/, start.sh) reside in the Skill's own directory and are not necessarily at the user's workspace root. The Skill can be installed in arbitrary locations: a project subdirectory, .agents/skills/, .codebuddy/skills/, and will work across IDEs (Claude Code / Codex / Cursor) in the future. Therefore, never assume "Skill root == Workspace root."
| Variable | Meaning | How to Obtain |
|---|---|---|
SKILL_ROOT | Skill's own directory (contains SKILL.md / scripts/ / capabilities/ …) | = The absolute path of the Base directory injected by the system when this Skill is loaded. The Agent must remember it. |
PROJECT_ROOT | User's current project root (= workspace root; the integration target for Path B) | = The absolute path of the current workspace root. |
Demo path (A) usesSKILL_ROOT(fetch capability sources + start core) andPROJECT_ROOT(where demo artifacts land); Integration path (B) usesSKILL_ROOT(fetch capability sources + start core) andPROJECT_ROOT(integration target). These two may or may not be the same — do not mix them up.
cd "$SKILL_ROOT" && python3 scripts/add-capability.py ...
# or
python3 "$SKILL_ROOT/scripts/add-capability.py" ...Do not write bare relative paths (e.g., python3 scripts/...) assuming they resolve against the workspace root — that was the root cause of bugs in previous versions.
$SKILL_ROOT / $PROJECT_ROOT, the Agent must substitute them with actual absolute paths before execution.start.sh / add-capability.py / post-install-patch.py) already self-locate(via __file__ / BASH_SOURCE), so as long as you invoke them with their absolute path, they work regardless of cwd.
SKILL_ROOT cannot be determined immediately, fall back to a one-shot detection (do not ask the user to move directories): find "$PWD" -maxdepth 4 -name SKILL.md -path '*ai-service*' 2>/dev/null | head -1If still not found, ask the user where the Skill is installed. Never ask the user to move the Skill directory to the workspace top level.
Trigger conditions (activate this Skill if any match):
Not applicable (refuse and explain):
Product positioning note: This Skill encapsulates TRTC Conversational AI (voice) capabilities. The selling point is "voice customer service." Therefore the demo scenario (Path A) is voice-first. If the user only wants plain text and merely reuses the RTC channel, advise them to configure it themselves. This Skill does not generate artifacts for text-only scenarios.
Purpose: Throughout the setup process, all of the AI's guidance text, ask_followup_question questions / options, prompts, and summaries must follow the natural language of the user's first prompt. Do not hardcode Chinese.Detection rules (complete after Skill start, before §3; store the result in the internal variable interaction_lang):
interaction_lang = zhinteraction_lang = en (approximate other languages with English)interaction_lang immediately and apply to all subsequent interactionsScope (must be followed):
| Scenario | Requirement |
|---|---|
| Path selection options | question and each option use interaction_lang |
| Path B Q&A dialogue | use interaction_lang |
| Three-Keys setup dialogue | use interaction_lang |
| Contract alignment options and checklist | use interaction_lang |
| Post-launch entry list / trial suggestions | use interaction_lang |
| Error recovery / warning messages | use interaction_lang |
Relationship with artifact UI language (only Path A involves UI):
interaction_lang controls the language of the setup process dialogue.recipe.yaml metadata.language) defaults to following `interaction_lang`,unless the user specifies otherwise.
interaction_lang.Do not default to Chinese in conversations just because SKILL.md itself is originally written in Chinese. Follow the user's language.
TRTC_REPORTING_NOTICE_REQUIRED_V1, finish the answer first; the installed post-answer Host Hook displays runtime/continuation-notice.md, so do not append or paraphrase it.context --question "<完整问题>"; fixed choices still use ask_followup_question.AI guidance text (output the following in interaction_lang):Before we officially start, the system will automatically check if your runtime environment meets the requirements. You don't need to do anything for this step — just wait a moment.
Checks performed:
If all checks pass, we'll automatically move to the next step. If something fails, the system will tell you exactly what's missing and how to fix it.
AI execution actions (substitute $SKILL_ROOT in all commands with the absolute path determined in §0 before execution):
python3 -c "import sys; assert sys.version_info >= (3, 9), sys.version" && echo OK || echo BAD_PYFail → tell the user:
Your Python version is too old. You need version 3.9 or above. You can download the latest version at https://www.python.org/downloads/. Once installed, we'll continue.
Do not proceed until the Python version is satisfied.
test -f "$SKILL_ROOT/capabilities/conversation-core/manifest.yaml" && echo OK || echo MISSING$SKILL_ROOT was set incorrectly. Use the find fallback from §0.2 item 4 to re-determine SKILL_ROOT, then rerun this check. Only ask the user for the Skill install location if it still fails.test -f "$SKILL_ROOT/capabilities/conversation-core/.env" && echo OK || echo MISSINGcd "$SKILL_ROOT" && python3 scripts/verify-credentials.py --type all (the file may have been copied from the template but not filled in yet). All ok → tell the user:I see you've configured your keys before. We can reuse them directly. If you want to reconfigure, just let me know.
Can skip §5 (unless the user explicitly wants to "reconfigure keys"). Any failure → §5 (already-valid entries need not be refilled).
AI guidance text:
Environment check passed! Now let's make a choice — how would you like to get started?
First required action: Use the ask_followup_question tool to present a single-choice question:
[{
"id": "path",
"question": "How would you like to set up your AI customer service?",
"options": [
"Quick Start — Get the agent running right away. You'll see the results in your browser (a web chat window + ticket management dashboard). You'll need to configure 3 keys, and the system will automatically install default capabilities. You should see results within 2-3 minutes. Best for first-timers who want to see 'what this thing looks like'",
"Integrate into My System (backend capabilities only) — If you already have your own website or app and want to plug in the AI customer service 'brain', choose this. The system will provide a set of API interfaces with no web UI generated. You'll need to configure 3 keys, then choose the interaction mode and additional capabilities"
],
"multiSelect": false
}]Fallback when Coding Agent does not support ask_followup_question: List both paths in natural language and collect the user's answer from the conversation. Do not make assumptions.Key boundaries the AI should proactively explain:
Whichever you choose, I'll walk you through it step by step. Here's a quick summary of the two paths: - Quick Start: I'll generate a complete customer service web interface for you. You'll be able to see and experience it right in your browser. - Integrate into My System: I'll give you the AI customer service backend capabilities only (API interfaces). The UI is yours — I'll hand you the API docs and sample code, and your developers can connect to them directly.
Trigger condition: §3.3 returned MISSING, or a key was subsequently judged as failed by verify-credentials.py. Substitute $SKILL_ROOT in commands with absolute paths before execution.AI guidance text:
To get the customer service agent running, you'll need to configure 3 keys — they're the access passes for cloud services. Don't worry, I'll walk you through each one.
We'll go in this order: first register and create the voice agent on the TRTC standalone site (this is the "core"), then get the Tencent Cloud API Key (this is the "control plane" that issues temporary credentials), last the LLM API Key (this is the "brain").
⚠️ Link Usage Red Line (violation = defect): The console URLs below are full URLs with tracking parameters (utm_campaign,_channel_track_key, …). When presenting these links to users, the Agent MUST copy-paste the full URL verbatim — do not simplify, truncate, or strip query parameters. These are marketing attribution entry points; simplifying the links causes tracking data loss.
Console links (VERBATIM):
| Purpose | Chinese users (show both, China site first) | English users (show only this) |
|---|---|---|
| Key 1 · TRTC (SDKAppID + SDKSecretKey) | 国内站:https://console.cloud.tencent.com/trtc/app?utm_campaign=skill&_channel_track_key=lDTHxeje<br>海外站:https://console.trtc.io?utm_campaign=Agent-skills-general&_channel_track_key=tR91l0wy | https://console.trtc.io?utm_campaign=Agent-skills-general&_channel_track_key=tR91l0wy |
| Key 2 · Tencent Cloud API | 国内站:https://console.cloud.tencent.com/cam/capi?utm_term=cam%E5%AF%86%E9%92%A5-%E5%9B%BD%E5%86%85&utm_campaign=skill&_channel_track_key=hTRQ0ctd<br>海外站:https://console.tencentcloud.com/cam/capi?utm_term=cam%E5%AF%86%E9%92%A5&utm_campaign=skill&_channel_track_key=zb44We6s | https://console.tencentcloud.com/cam/capi?utm_term=cam%E5%AF%86%E9%92%A5&utm_campaign=skill&_channel_track_key=zb44We6s |
Never show the 国内站 links to English users. Tell Chinese users to get Key 1 and Key 2 from the same site.
Only the SDKAppID is collected in chat. The SDKSecretKey, SecretId / SecretKey and the LLM key / URL / model are typed into .env by the user. Never ask for a secret in chat; if the user pastes one anyway, do not repeat it — ask them to put it in .env instead.
Step 0 · Prepare `.env`. Confirm .env is git-ignored if the project is a git repo (add it to .gitignore first if not), then:
cd "$SKILL_ROOT/capabilities/conversation-core" && (test -f .env || cp .env.example .env) && chmod 600 .envShort-circuit: If session already has root-collected sdkappid (non-zero int, from trtc/flows/collect-sdkappid.md), do not ask — just write it.
Otherwise the AI should say (link per the table above):
Key 1 — TRTC Application Credentials. This is the voice channel for your agent. 1. Go to <Key 1 link> and log in / register 2. Create an RTC Engine application (supports Conversational AI) 3. Inside the app, find the SDKAppID (a number) and send me only the SDKAppID
After receiving it (or on short-circuit):
TRTC_SDK_APP_ID= and TRTC_REGION= lines of .env (no secrets are in the file yet). TRTC_REGION is derived, never asked: SDKAppID starting with 14 or 16 → cn, any other valid SDKAppID → intl; keep an existing value the user set explicitlypython3 "<当前 trtc skill 根目录>/tools/reporting.py" capture-sdkappid --input-stdin --ide <ide> with a JSON-serialized stdin object containing only the explicitly supplied SDKAppID, known product / framework / skillname, source:"domain-fallback", and cwd; never include any secret. Reporting failure must not block integration.envThe AI should say (substitute the absolute path of $SKILL_ROOT/capabilities/conversation-core/.env; links per the table above; translate to Chinese for Chinese users):
SDKAppID saved. Please open this file and fill in the remaining keys yourself, then save and reply "done" — I'll verify them all: <absolute .env path>>
1. `TRTC_SDK_SECRET_KEY` — the rest of key 1, on the same application page under "Server-side Integration". ⚠️ The server-side SDKSecretKey, not the client-side STSecretKey 2. `TENCENT_CLOUD_SECRET_ID` / `TENCENT_CLOUD_SECRET_KEY` — key 2, Tencent Cloud API credentials (permissions, STS tokens). Same account and site as key 1, no need to register again: - <Key 2 link> 3. `LLM_API_KEY` / `LLM_API_URL` / `LLM_MODEL` — key 3, the "brain". Any OpenAI-compatible provider you already use; all three values must come from the same provider. For OpenAI you can keep the default URL and model
If the user asks where to get an LLM key, show this table (do not pick for them):
| Provider | Key page | Best value |
|---|---|---|
| OpenAI | https://platform.openai.com/api-keys | gpt-4o-mini |
| Anthropic | https://console.anthropic.com/settings/keys | claude-3-haiku |
| Google AI | https://aistudio.google.com/apikey | gemini-1.5-flash |
| DeepSeek | https://platform.deepseek.com/api_keys | deepseek-chat |
| Together | https://api.together.ai/settings/api-keys | llama-3-8b |
| Groq | https://console.groq.com/keys | llama-3.1-8b |
Step 3 · Verify. After the user replies, run cd "$SKILL_ROOT" && python3 scripts/verify-credentials.py --type all. Parse per §5.5: all ok:true → continue; any failure → list every failing item at once, ask the user to fix it in `.env` and reply again, then re-run.
verify-credentials.py reads .env itself.envok/error/latency_ms.env is chmod 600 (done in Step 0)On failure, ask the user to fix the entry in `.env` and reply — never ask them to send the key in chat.
| error | Meaning | What the AI should tell the user |
|---|---|---|
| E000 | Credential not configured / empty | "This entry in .env is still empty — fill it in, save, and let me know" |
| E001 | Tencent Cloud API verification failed | "Tencent Cloud API verification failed. Common causes: ① Id/Key order might be swapped ② Key may have been disabled ③ STS service not enabled on your account ④ the key is from a different site than key 1. Please check in .env and let me know" |
| E002 | TRTC verification failed | "TRTC verification failed. Please double-check in .env: ① Does the SDKAppID belong to your account ② Did you mix up SDKSecretKey and STSecretKey" |
| E003 | LLM verification failed | "LLM verification failed. Please check that LLM_API_KEY, LLM_API_URL and LLM_MODEL in .env all come from the same provider" |
| E004 | Network unreachable | "Cannot reach the verification server. Please check: ① Do you need a proxy ② Is there a corporate firewall ③ Is your network working. You can also skip deep verification and continue" |
User selected A in §4. Default artifact: Voice Customer Service UI (TRTC real connection, FAQ silent RAG, handoff queue animation + simulated connection, product/order business panel). Substitute $SKILL_ROOT in all commands with absolute paths before execution.AI guidance text (Path A entry point): Alright, going with the Quick Start path! I'll set up the entire customer service system for you. You don't need to do anything — just wait a moment.
>
This path will automatically install the following capabilities: - Conversation capability: The agent can actually understand what you say and respond (because real AI keys are configured) - Human handoff: You'll see the handoff flow and UI (using demo data) - Knowledge base: You'll see KB search results in action (using demo documents) - Session summary: Default-installed in Path A — when a handoff ticket is created, an LLM-generated summary of the conversation is written into the ticket Description so agents see the context immediately
>
Once set up, you'll open your browser and see a full customer service chat interface and a ticket management dashboard.
| Parameter | Default | Description |
|---|---|---|
| Deployment directory | $PROJECT_ROOT/ai-customer-service-demo/ | Where the demo UI lands (independent of the Skill folder, easy for later customization); use a different directory if the user requests it |
| Port | 3000 | If occupied or user specifies a different one: bash "$SKILL_ROOT/start.sh" --port <N>, then sync the port in all subsequent health checks / URLs |
Step 1: Configure the Three Keys
execute_command("test -f \"$SKILL_ROOT/capabilities/conversation-core/.env\" && echo OK || echo MISSING")Step 2: Assemble Capability Packages
AI should tell the user: Installing dependencies and assembling default capabilities — this should take about 30-60 seconds...
execute_command("cd \"$SKILL_ROOT\" && python3 scripts/add-capability.py knowledge-base human-handoff --apply --json")reports[*].errors == [], no fatal injection.error$SKILL_ROOT/auto_adapters/integration_templates/generic-frontend.mdStep 2.5: Post-Install Patch (Must Run)
execute_command("cd \"$SKILL_ROOT\" && python3 scripts/post-install-patch.py"){"ok": true, ...}.env (existing values untouched)server.py's StaticFiles(html=True)Step 3: UI Overlay (Must Run — Path A Exclusive) —— Default Voice Customer Service UI
$PROJECT_ROOT/ai-customer-service-demo/ (independent of Skill directory, easy for later edits) execute_command(
"mkdir -p \"$PROJECT_ROOT\"/ai-customer-service-demo/admin && \
cp \"$SKILL_ROOT\"/scenarios/customer-service/ui/voice-customer-service/{index.html,app.js,styles.css,data.js,mock-shop.json,tokens.css} \
\"$PROJECT_ROOT\"/ai-customer-service-demo/ && \
cp -R \"$SKILL_ROOT\"/scenarios/customer-service/ui/admin-board/. \
\"$PROJECT_ROOT\"/ai-customer-service-demo/admin/ && \
echo \"WEB_DEMO_DIR=$PROJECT_ROOT/ai-customer-service-demo\" >> \"$SKILL_ROOT\"/capabilities/conversation-core/.env"
)$PROJECT_ROOT/ai-customer-service-demo/ contains index.html / app.js / styles.css / data.js / mock-shop.json / tokens.css + admin/ subdirectory, and WEB_DEMO_DIR is written to .env$SKILL_ROOT/scenarios/customer-service/ui/voice-customer-service/ is intactStep 4: Proactively List business_contract (enter §9)
Step 5: Start the Demo
AI should tell the user: Starting the customer service system. The first launch needs to install some dependency packages and may take 30-60 seconds. Please wait...
execute_command("cd \"$SKILL_ROOT\" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 &")execute_command("sleep 8 && curl -sS http://localhost:3000/api/v1/health")execute_command("sleep 25 && curl -sS http://localhost:3000/api/v1/health") try againtail -80 /tmp/ai-cs-start.log check for pip install errors / port conflicts{"status":"ok",...} → Proceed to Step 6Step 6: Output Entry List + Trial Suggestions
The AI should say: All done! Your AI customer service agent is up and running. Open the following URLs in your browser to see it in action:
| Page | URL | Description |
|---|---|---|
| AI Voice Agent | http://localhost:3000 | (customer service chat interface) |
| Admin board | http://localhost:3000/static/admin/ | (ticket management dashboard) |
| API docs (Swagger) | http://localhost:3000/docs | (API documentation) |
| Health probe | http://localhost:3000/api/v1/health | (health check) |
Try saying / typing:
· "How do I get a refund" → AI replies; KB silently augments answer
· "Talk to agent" → handoff queue + 8s progress bar + simulated connect
· Click any product / order card → auto-asks the AI about that itemNote: The human handoff and knowledge base are using simulated data, so you won't see real business integration effects. If you want to connect to a real business system, you can start over and choose "B — Integrate into My System."
cd "$SKILL_ROOT" or use absolute paths — see §0)capabilities/*/src/core/ (this is the skeleton layer; do not touch)/ at the conversation-core built-in voice self-check page → not the intended artifact)/admin/tickets (the correct path is `/static/admin/`)git commit / git push (unless the user explicitly requests it)User selected B in §4. Key positioning: Integrate TRTC Conversational AI backend capabilities into the user's existing project (PROJECT_ROOT). -conversation-coreis the core: must end-to-end verify the voice conversation pipeline (test until you can actually converse). - Other incremental capabilities (knowledge-base / human-handoff / session-summary / tool-calling): Only deliver interface specifications + mock implementations + sample code. The user replaces them with their own systems as needed. - This path NEVER generates any frontend UI — the UI is the user's own frontend/backend responsibility.
AI guidance text (Path B entry point — must explicitly state boundaries): Alright, going with the "Integrate into My System" path. This path will plug the AI customer service backend capabilities into your existing project.
>
Here's what I'll do: - Install the voice conversation core (conversation-core) and run it end-to-end to confirm it can actually converse - For extra capabilities like knowledge base, human handoff, session summaries, etc., I'll only provide interface specs + mock implementations + sample code. You swap in your own real systems as needed - I will not generate any web UI — the UI is handled by your own project's frontend
>
Now, let's walk through a few steps: first confirm your project, then pick capabilities, and finally choose the interaction mode for the agent.
PROJECT_ROOT (default = current workspace root). If the user's project is in a subdirectory, have them specify it as --target-project. cd "$SKILL_ROOT" && python3 scripts/add-capability.py --list --jsonTech stack detection is triggered automatically by --target-project during Step 7.3 assembly (stack_detector). If auto-detection is inaccurate, override with --tech-stack <react|vue|node|python|java|...>.
execute_command("test -f \"$SKILL_ROOT/capabilities/conversation-core/.env\" && echo OK || echo MISSING")The AI should say (using ask_followup_question multi-select mode): Now let's decide what extra capabilities the agent should have. Besides the built-in voice conversation capability, you can add the following. You can pick multiple, or none at all. Without any extras, the agent will only have basic conversation ability.| # | Capability Package | Description | What you'll get |
|---|---|---|---|
| 1 | Knowledge Base | FAQ / KB search | Upload a return policy PDF — the agent automatically answers "How do I return this?" |
| 2 | Human Handoff | Auto-escalate to a human when the bot can't handle it | Complex issues (complaints, refund disputes) are automatically routed to a human agent, with a ticket dashboard |
| 3 | Tool Calling | Let the agent query your system's data | Customer asks "Where's my order?" → agent queries your database and returns shipping status |
| 4 | Session Summary | Auto-generate a summary after each conversation | After each chat, a summary is written so you can review what the customer said and archive it |
[{
"id": "capabilities",
"question": "Which additional capabilities do you need? (multi-select)",
"options": [
"① Knowledge Base — FAQ / KB search",
"② Human Handoff — Escalate to human + ticket flow",
"③ Tool Calling — Let AI call your business tools",
"④ Session Summary — Auto-generate summaries after sessions",
"(None — just basic conversation)"
],
"multiSelect": true
}]Made your choice? Just tell me the numbers (e.g., "1, 2, 3" or "all").
Assembly command (renders incremental capability adapters / samples into the user's project):
cd "$SKILL_ROOT" && python3 scripts/add-capability.py <selected capabilities...> \
--target-project "$PROJECT_ROOT" --apply --json
# If none selected, skip this command (only runs voice core)--target-project triggers auto_adapters three-tier fallback rendering:$PROJECT_ROOTPost-install patch (must run):
cd "$SKILL_ROOT" && python3 scripts/post-install-patch.pyThe AI should say (using ask_followup_question single-choice mode): Now let's decide the agent's "communication method" — how will your customer service agent interact with customers? Here are 4 options — pick the one that best fits your business:| # | Modality | Plain Description | Best For |
|---|---|---|---|
| 1 | Text-only IM | Agent replies via text chat only | Web live chat, in-app messaging, WeChat customer service |
| 2 | Text + TTS | Agent replies in text, with text-to-speech read aloud to the customer | Need voice feedback but don't want a phone line — e.g., smart speakers, app voice assistants |
| 3 | Full Modality | Text and voice both available — the most complete interaction | High-end scenarios requiring both text and voice |
| 4 | Voice-only Call | Agent communicates only via voice call, no text interface | Call centers, 400-phone customer service, voice hotlines |
[{
"id": "modality",
"question": "Which communication method?",
"options": [
"① Text-only IM — Chat via text",
"② Text + TTS — Text replies + voice readout",
"③ Full Modality — Both text and voice",
"④ Voice-only Call — Voice call only"
],
"multiSelect": false
}]Made your choice? Just tell me the number.
Since no UI is provided, voice quality is verified by the user in their own frontend. The Skill-side acceptance criteria are as follows (all three passing = end-to-end verified):
GET /api/v1/health — three LEDs (tencent_cloud / trtc / llm) all greenPOST /api/v1/agent/start returns TaskId / SessionId successfully$PROJECT_ROOTStart core:
cd "$SKILL_ROOT" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 &
sleep 8 && curl -sS http://localhost:3000/api/v1/healthThe AI should say: Assembly complete! Your AI customer service backend capabilities are ready. Here's what has been delivered:
/api/v1/* backend API contract (output in §9)/docs (Swagger) after launchWhat you need to do next: hand the API checklist to your developers and have them follow the documentation to integrate the AI customer service capabilities into your website or app. If you run into issues during integration, come back anytime.
capabilities/*/src/core/ skeleton layerWhen human-handoff and session-summary are both installed they automatically link up — no extra configuration by the AI needed. In Path A, session-summary is default-installed (seerecipe.yamlinstall:), so the linkage is active out of the box. In Path B it links up only if the user selected session-summary.
Behavior: When human-handoff creates a ticket, it best-effort triggers session-summary to generate an LLM one-paragraph summary of the conversation (from AI connect → handoff trigger) and writes it into the ticket's `Description` field. When an agent opens the ticket details on the dashboard, they directly see this conversation summary under "Conversation summary" — no separate "Session Summary" block, no manual "Generate Summary" click needed.
Implementation notes (for maintainers):
capabilities/human-handoff/src/summary_link.py (attach_summary_to_ticket)capabilities/session-summary/src/summarizer.py → summarize_paragraph(record) (LLM, uses LLM_API_KEY / LLM_API_URL / LLM_MODEL). Falls back to leaving the description unchanged if LLM is not configured or the session has no recorded turns._capability_loader; not installed / any exception → silently skip, does not affect the main handoff flowadmin-board/app.js renders the ticket description as "Conversation summary"; the legacy structured session_summary block has been removed/handoff/request via POST /api/v1/summary/{session_id}/record, so the recorder has the turns to summarizeThe LLM summary call runs synchronously inside the ticket-creation chain and may take a few seconds. This is acceptable because the Path A frontend fires/handoff/requestwithout awaiting it (the handoff animation plays in parallel); the ticketDescriptionis populated by the time the agent refreshes the board.
Trigger condition: mandatory after assembly is complete. Substitute $SKILL_ROOT in commands with absolute paths before execution.Read manifest.yaml.business_contract.external_apis for each capability package. Only list entries where `direction == outbound`, outputting in the following natural language format:
✓ Installed: conversation-core + knowledge-base + human-handoff.
This session uses mock / local implementations as demo data.
Our capability packages call the following external business APIs:
1. POST /tickets ← human-handoff ticket creation
2. GET /tickets/{ticket_id} ← human-handoff ticket status query
3. POST /tickets/{ticket_id}/cancel ← human-handoff ticket cancellation
4. POST /faq/search ← knowledge-base FAQ search
5. GET /faq ← knowledge-base FAQ list
6. POST /faq ← knowledge-base FAQ create/update
7. DELETE /faq/{entry_id} ← knowledge-base FAQ deletePath B reminder: The contract checklist is one of the core deliverables to the user. Even if the user chooses "run with mocks first," leave this checklist with them.
The AI should say: Do you want to switch to a real ticketing / knowledge base system? - Connect to my own system and adapt the interfaces accordingly - Run with mock data for now: skip interface adaptation and start directly
Use ask_followup_question single-choice:
write_to_file(/tmp/adapt_<cap>.curl.txt, <user's text>)execute_command("cd \"$SKILL_ROOT\" && python3 scripts/contract-adapt.py <cap> --curl-file /tmp/adapt_<cap>.curl.txt --json")or --openapi-file <path>
{"level":"L1","artifact":"<path>"} → Tell the user "Generated user_custom.py — ready to enable"{"level":"L2","artifact":"<path>","todos":[...]} → List TODOs for the user to fill in{"level":"L3","guide":"INTERFACE_ADAPT.md#section"} → Have the user follow the documentationwrite_to_file append the non-secret lines to $SKILL_ROOT/capabilities/conversation-core/.env; if a token is needed, leave HH_REST_TOKEN= empty and ask the user to fill it in themselves (§5.4):
HH_ADAPTER=user_custom # or KB_ADAPTER=user_custom
HH_REST_BASE_URL=https://...
HH_REST_TOKEN= # if applicable — filled in by the userDefault port is 3000. Adjust with--port <N>if needed. If port is changed, sync all URLs / health checks below. Substitute$SKILL_ROOTin commands with absolute paths before execution.
cd "$SKILL_ROOT" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 &
# Custom port: cd "$SKILL_ROOT" && nohup bash start.sh --port 8080 > /tmp/ai-cs-start.log 2>&1 &sleep 8 && curl -sS http://localhost:3000/api/v1/health
# If connection refused: wait longer
sleep 25 && curl -sS http://localhost:3000/api/v1/healthExpected: response contains "status":"ok", three LEDs (tencent_cloud / trtc / llm) all ok.
Setup complete. Open the following URLs:
· AI Voice Agent http://localhost:3000 (default)
· Admin board http://localhost:3000/static/admin/
· API docs (Swagger) http://localhost:3000/docs
· Health probe http://localhost:3000/api/v1/health
To stop: lsof -ti :3000 -sTCP:LISTEN | xargs killCorrect entry: The admin dashboard path is/static/admin/(not/admin/tickets— that route does not exist).
The default Demo uses Tencent's in-house engines for STT / TTS and the LLM you configured in Key 3. If you want to switch to a different model provider — for example, to try a stronger LLM, support a different language via STT, or pick a different voice — this section walks you through the lowest-cost path.
AI should say:
Your default demo is up and running 🎉. Before we call it done, would you like to take a look at advanced configuration? It's completely optional — your current setup works perfectly. But if you want to try a different voice, support another language, or swap to a different LLM, we can do it right now in just a few minutes.
If user says no → output the final wrap-up message (§10.3A.2 below) and end.
If user says yes → walk through the following three sections in order. Each is independent — the user can choose to skip any of them.
#### 10.3A.1.1 Switch STT (Speech-to-Text) model
STT turns the customer's voice into text for the LLM to understand. If you want to recognize a different language (the default is optimized for zh + en), Tencent offers a high-accuracy bigmodel engine with 30+ languages.
AI should say:
Let's start with STT — the speech-to-text engine. Tencent's default is fine for Chinese and English. If you want to support more languages, switch to the bigmodel engine (doc: https://trtc.io/document/69592?product=conversationalai).>
Supported languages whenengine_model_type=bigmodel:zh(Chinese),en(English),yue(Cantonese),ar(Arabic),de(German),fr(French),es(Spanish),pt(Portuguese),id(Indonesian),it(Italian),ko(Korean),ru(Russian),th(Thai),vi(Vietnamese),ja(Japanese),tr(Turkish),hi(Hindi),ms(Malay),nl(Dutch),sv(Swedish),da(Danish),fi(Finnish),pl(Polish),cs(Czech),fil(Filipino),fa(Persian),el(Greek),ro(Romanian),hu(Hungarian),mk(Macedonian). To switch STT engine, append these two lines to your.envand restart the service (no new keys needed): ``bash # STT engine — set engine_model_type=bigmodel to enable multi-language STT_ENGINE_MODEL_TYPE=bigmodel STT_ENGINE_LANGUAGE=zh # pick from the table above`Then restart:lsof -ti :3000 -sTCP:LISTEN | xargs kill && cd "$SKILL_ROOT" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 &`
#### 10.3A.1.2 Switch LLM (Language Model)
The LLM is the "brain" of your customer service agent. You already configured one in Key 3 — if you want to try a different one, the cheapest path is to use the same .env values, just point to a different provider.
AI should say:
For the LLM, swap providers by changing 3 lines in .env — no code change:| Provider | Cost-effective pick | Get API Key |
|---|---|---|
| DeepSeek | deepseek-chat (best for Chinese, ~30x cheaper than gpt-4o) | https://platform.deepseek.com/api_keys |
| OpenAI | gpt-4o-mini | https://platform.openai.com/api-keys |
| Anthropic | claude-3-haiku | https://console.anthropic.com/settings/keys |
| Google AI | gemini-1.5-flash | https://aistudio.google.com/apikey |
| Together | meta-llama/Llama-3-8b-chat-hf | https://api.together.ai/settings/api-keys |
| Groq | llama-3.1-8b-instant | https://console.groq.com/keys |
Example (DeepSeek — cheapest for Chinese): ``bash LLM_API_KEY=sk-your-key LLM_API_URL=https://api.deepseek.com/v1/chat/completions LLM_MODEL_NAME=deepseek-chat`Then restart:lsof -ti :3000 -sTCP:LISTEN | xargs kill && cd "$SKILL_ROOT" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 &`
#### 10.3A.1.3 Switch TTS (Text-to-Speech) voice
TTS turns the LLM's text replies into voice. Tencent's default voices are good for most cases. If you want a different voice (e.g., a specific timbre, accent, or language), browse the TTS voice library.
AI should say:
For TTS, browse the voice library: https://trtc.io/document/68340?product=conversationalai
>
To switch TTS voice, add to.envand restart: ``bash TTS_VOICE_TYPE=Chinese_Female_Shuanger`> 💡 **Tip**: If you want a non-Chinese voice, make sure you also setSTT_ENGINE_MODEL_TYPE=bigmodelandSTT_ENGINE_LANGUAGE=<matching code>` in §10.3A.1.1, otherwise the customer's speech and the agent's voice will be in different languages.
All set! Your AI customer service agent is fully configured and running. 🎉
Quick recap of what you have:
· AI Voice Agent http://localhost:3000 (default)
· Admin board http://localhost:3000/static/admin/
· API docs (Swagger) http://localhost:3000/docs
· Health probe http://localhost:3000/api/v1/health
You can switch STT / LLM / TTS models at any time by editing `.env` and restarting. Have fun! 🚀
To stop: lsof -ti :3000 -sTCP:LISTEN | xargs killBackend capabilities integrated. Verification:
· Health probe http://localhost:3000/api/v1/health (3 LEDs green)
· Control-plane POST /api/v1/agent/start → returns TaskId / SessionId
· API docs (Swagger) http://localhost:3000/docs (integration entry point)
Delivered to your project ($PROJECT_ROOT):
· Integration sample code (room entry / control), invocation order: get_config → enter room → agent/start → agent/control → agent/stop
· Outbound contract checklist + mock descriptions for each incremental capability (swap with your real system as needed)
UI is implemented by your own frontend. Verify voice quality from your frontend after entering a room.
To stop: lsof -ti :3000 -sTCP:LISTEN | xargs killIf you encounter any of the following issues, here are the corresponding solutions:
| Issue | Cause | Solution |
|---|---|---|
| Key verification failed | Configured key expired or incorrect | Go back to §5 and ask the user to fix only the failed entry in .env, then re-verify |
| Port is occupied | Port 3000 is in use by another program | Switch to a different port (e.g., --port 8080), or stop the program using port 3000 |
| Network unreachable | Corporate network or firewall restriction | Check if you need a proxy, or contact your network administrator to open the relevant domains |
| Python version too old | Python < 3.9 | Download the latest version from https://www.python.org/downloads/ |
| Error on startup | Dependency version conflict | The system will auto-fix it. If errors persist, send me the error message |
| Browser shows old UI (Path A) | Browser cached the old page | Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows) to force refresh |
/admin/tickets returns 404 (Path A) | That route doesn't exist | The correct entry is http://localhost:3000/static/admin/ |
#### Can't find assets / "No such file" / scripts won't run
SKILL_ROOT (most common issue in older versions).SKILL_ROOT per §0. All commands must cd "$SKILL_ROOT" or use absolute paths. Rerun.#### .env exists but keys are invalid
.env (keep others)#### Port is occupied
execute_command("lsof -ti :3000 -sTCP:LISTEN")cd "$SKILL_ROOT" && bash start.sh --port 8080kill <PID> (requires explicit user consent)#### add-capability reports circular dependency
#### LLM verification failed but user is using a non-OpenAI service
LLM_API_URL and LLM_MODEL:https://api.deepseek.com/chat/completions, model: deepseek-chatcd "$SKILL_ROOT" && python3 scripts/verify-credentials.py --type llm#### verify-credentials.py returns E004 (network unreachable)
HTTPS_PROXY=... to .env--no-deep for local UserSig self-consistency check only#### NameError: name 'session_id' is not defined after startup
cd "$SKILL_ROOT" && python3 scripts/post-install-patch.py#### contract-adapt.py parse failure
{"level":"L3", ...} → Guide the user to read the corresponding capability package's INTERFACE_ADAPT.mdSubstitute all$SKILL_ROOT/$PROJECT_ROOTwith absolute paths before execution. Alwayscd "$SKILL_ROOT"or use absolute paths when calling scripts.
| Command | Purpose | ||
|---|---|---|---|
python3 -c "import sys; assert sys.version_info >= (3,9)" | Prerequisite check | ||
| `test -f "$SKILL_ROOT/<path>" && echo OK \ | \ | echo MISSING` | File existence check |
find "$PWD" -maxdepth 4 -name SKILL.md -path '*ai-service*' | SKILL_ROOT fallback detection | ||
| `cd "$SKILL_ROOT" && python3 scripts/verify-credentials.py [--type tencent\ | trtc\ | llm] [--no-deep]` | Key verification |
cd "$SKILL_ROOT" && python3 scripts/add-capability.py <names> --apply --json [--target-project "$PROJECT_ROOT"] [--tech-stack ...] | Capability assembly | ||
cd "$SKILL_ROOT" && python3 scripts/post-install-patch.py | Post-install patch | ||
| `cd "$SKILL_ROOT" && python3 scripts/contract-adapt.py <name> [--curl-file ... \ | --openapi-file ...] --json` | API contract adaptation | |
cp "$SKILL_ROOT"/scenarios/customer-service/ui/voice-customer-service/{index.html,app.js,styles.css,data.js,mock-shop.json,tokens.css} "$PROJECT_ROOT"/ai-customer-service-demo/ | UI overlay (Path A only) | ||
cp -R "$SKILL_ROOT"/scenarios/customer-service/ui/admin-board/. "$PROJECT_ROOT"/ai-customer-service-demo/admin/ | Admin board mount (Path A only) | ||
mkdir -p "$PROJECT_ROOT"/ai-customer-service-demo/admin | Create demo deployment directory (Path A only) | ||
echo "WEB_DEMO_DIR=<path>" >> "$SKILL_ROOT"/capabilities/conversation-core/.env | Write demo directory path (Path A only) | ||
cd "$SKILL_ROOT" && bash start.sh [--port N] [--https] | Launch | ||
cd "$SKILL_ROOT" && nohup bash start.sh > /tmp/ai-cs-start.log 2>&1 & | Background launch | ||
sleep N && curl -sS http://localhost:3000/api/v1/health | Health check | ||
tail -80 /tmp/ai-cs-start.log | Startup failure diagnostics | ||
lsof -ti :3000 -sTCP:LISTEN | Check port usage | ||
chmod 600 "$SKILL_ROOT/capabilities/conversation-core/.env" | Tighten permissions |
| Command | Reason Prohibited |
|---|---|
python3 scripts/setup-credentials.py validate-tencent-cloud --secret-id ... | Key passed via command line → shell history leak |
echo $TENCENT_CLOUD_SECRET_ID | shell history leak |
cat "$SKILL_ROOT/capabilities/conversation-core/.env" | May leak via terminal recording / screenshots |
git add . && git commit | Credentials may be committed by mistake |
| Any command with plaintext keys as arguments | Same as above |
Bare relative paths to call scripts (python3 scripts/... without cd "$SKILL_ROOT") | Wrong cwd assumption → can't find assets |
| Path | Purpose |
|---|---|
$SKILL_ROOT/capabilities/conversation-core/.env | Key write |
$PROJECT_ROOT/<adapter rendered artifact> | Path B: integration samples (written by script, not AI) |
$SKILL_ROOT/capabilities/<cap>/src/adapters/user_custom.py | Generated by contract-adapt.py |
/tmp/adapt_<cap>.curl.txt | Temporary storage for user's curl |
/tmp/ai-cs-start.log | nohup startup log |
Other file writes require explicit user confirmation before writing. Special note: capabilities/conversation-core/src/agent.py and capabilities/conversation-core/src/server.py are the skeleton layer. The AI should not directly edit them by hand.
Path B generates no UI. This section does not apply to Path B.
Path A UI must follow $SKILL_ROOT/scenarios/customer-service/ui/design-system/DESIGN_GUIDELINES.md:
| Item | Mandatory Requirement |
|---|---|
| Theme | Light glassmorphism locked (soft purple + light pink + pale blue ambient over #f7f3ff; no dark mode toggle) |
| Colors | Everything via CSS variables from tokens.css; no hardcoded hex values |
| Font | SF Pro / Inter / Helvetica Neue, Chinese fallback to system default |
| Icons | Lucide / Phosphor style monoline SVG icons, sizes: 16/20/24/32 |
| Emoji | Completely disabled in the UI rendering layer (use SVG icons + text instead) |
| Glassmorphism panels | backdrop-filter: blur(20px) + @supports fallback |
The 3 LEDs in the top right each show a tooltip on hover:
| LED | Title | Explanation |
|---|---|---|
| Cloud | Tencent Cloud API | Control-plane (CAM/STS); used to issue temporary credentials |
| TRTC | TRTC (Real-Time Communication) | Data-plane media channel; carries voice streams / subtitles / custom messages |
| LLM | LLM provider | Inference engine; OpenAI-compatible protocol; swappable with DeepSeek / GPT / Claude, etc. |
Final Reminders (for the Coding Agent to internalize): - 🔴 Path baseline first: DetermineSKILL_ROOT(= injected Base directory) andPROJECT_ROOTper §0 before anything else. Alwayscd "$SKILL_ROOT"or use absolute paths for all script/asset commands. Never ask the user to move directories. - At each step, first call the tool to get facts, then explain to the user (don't answer from memory) - Tool call failure → give the user a stderr summary; do not hide errors - Uncertain field / path → useread_fileto check the manifest, then answer - Strictly follow §12 Tool Whitelist and §5.4 Security Red Lines throughout - This Skill's selling point is voice; text-only requests → advise the user to configure it themselves; do not generate artifacts - Path A must run all 6 steps. Never skip Step 2.5 (post-install-patch) or Step 3 (UI overlay) - Path B never generates any UI; core end-to-end verified + incremental capabilities provide specs/mocks/samples only - human-handoff legacy API field isstate(values:waiting/connected/closed/canceled/timeout), notstatus/queued/cancelled
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.