# Voicenter Bot Spec Designer

> Designs the structural skeleton of a Voicenter Bot via interview. Use this skill when the user wants to create, design, scope, or modify a Voicenter voice/chat bot — phrases like "design a bot", "create an agent spec", "build a Voicenter bot", "patch this bot", "add an intent", "change the bot's persona", "modify the flow graph", or any reference to the Agent Spec Designer / Skill 1 in the Voicen…

- **Type:** Skill
- **Install:** `agentstack add skill-voicenterteam-claude-marketplace-voicenter-bot-spec-designer`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [VoicenterTeam](https://agentstack.voostack.com/s/voicenterteam)
- **Installs:** 0
- **Category:** [Content & Media](https://agentstack.voostack.com/c/content-and-media)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [VoicenterTeam](https://github.com/VoicenterTeam)
- **Source:** https://github.com/VoicenterTeam/claude-marketplace/tree/main/references/skills/voicenter-bot-spec-designer

## Install

```sh
agentstack add skill-voicenterteam-claude-marketplace-voicenter-bot-spec-designer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Skill 1 — Agent Spec Designer

This skill produces the **structural skeleton** of an Agent Spec markdown file through interview. It is one of three skills in the Voicenter Bot generation pipeline:

- **Skill 1 (this skill):** structural design via interview → fills spec sections 1, 2, 3, 4, 4.5, 6 (initial), 7 (init); creates section 5 stubs marked `[structural]`.
- **Skill 2 (Intent Detail Author):** language-heavy per-intent content → fills section 5 entries, marks them `[detailed]`.
- **Skill 3 (JSON Assembler & Publish):** mechanical projection of the spec into Bot JSON wire format.

Source of truth is the spec markdown. No skill invents values.

---

## 1. Required reading at invocation

Before any user interaction, load context from these references. Path conventions assume project files are accessible.

| Read | Why |
|---|---|
| Doc 1 §6.B.1 — `prompts` bundle (5 fields) | Skill 1 authors all five |
| Doc 1 §11 — RT=1/2/3/4 cross-RT field summary | Phase 4 per-RT capture |
| Doc 1 §12 — `ParameterTypeId` catalog | Slot type mapping (Appendix B in this file) |
| Doc 1 §13 — Mustache + variable categories | Section 4.5 inventory + advisory check |
| Doc 1 §14.3 — Anti-patterns | Iron rules Skill 1 enforces (Appendix A) |
| Doc 2 §3 — Agent Spec template | What Skill 1 writes |
| Doc 2 §4 — Skill 1 architecture | What Skill 1 does |

Also load these files from this skill's package:

- `model-catalog.md` — AI model configs + voice catalog (Phase 1)
- `spec-skeleton.md` — empty Agent Spec template
- `trigger-detection-rules.md` — Deep Research nudge triggers (Phase 2/3 boundary)
- `templates/voice-default.md`, `templates/chat-default.md` — inactive-channel templated defaults (Phase 2)

---

## 2. Setup

### 2.1 Detect runtime

| Signal | Runtime |
|---|---|
| Conversation in claude.ai or mobile app, no workspace file system, no `agent-spec.md` accessible | **Single-conversation** |
| Workspace file system available (Claude Code), tool calls to read/write workspace files possible | **Claude Code** |

State the detected runtime to the user. They can correct.

### 2.2 Detect mode

| Signal | Mode |
|---|---|
| Spec file attached (uploaded by user) OR `agent-spec.md` present in workspace | **Patch** |
| No spec file present | **Greenfield** |

State the detected mode to the user. They can override (forced greenfield with prior spec attached requires explicit confirmation that existing spec content will be discarded).

### 2.3 Confirm and start

State both. Confirm the bot's working name (or a placeholder for greenfield). Then proceed to Section 3 (greenfield) or Section 4 (patch).

---

## 3. Greenfield mode

Four phases, in order. Phase boundaries are not strict — revisit earlier phases if later answers reveal omissions. The Deep Research nudge falls between Phase 2 and Phase 3.

### 3.1 Phase 1 — Identity, Channels, Model, Caller-silence

**Goal:** populate spec sections 1 and 3.

Ask, in order:

1. **Bot name** (free text, often Hebrew). Required.
2. **Identifier**: ask "What ASCII identifier should this bot be filed under? (snake_case; used as the filename prefix when Skill 3 emits the JSON)". If Bot Name is already pure ASCII, default to its snake_cased form and ask only for confirmation. Required. Written to spec section 1 as `**Identifier:**`.
3. **Description** (free text). May duplicate the name. Required.
4. **Customer Account ID** (integer, references the Voicenter customer account). If user doesn't know: mark ``.
5. **Primary language** (BCP-47, e.g., `he-IL`, `en-US`). Required.
6. **Channel scope:** voice / chat / voice+chat. Required.
7. **If voice active:** voice name. Present `model-catalog.md` voice catalog (`Puck`, `Orus`, plus any others); user picks by name or supplies any other string the provider supports.
8. **AI model config:** present `model-catalog.md` model list. User picks by name → map to `AIModelConfigID` + `AIModelTypeId`. Override path: user supplies raw IDs directly. If user can't decide: mark ``.
9. **Caller silence:** "Does this bot need to handle caller silence?" One yes/no.
   - If yes: walk the four fields — `silence_duration` (seconds, int), `silence_loops` (int), `silence_sentence` (text, Mustache OK), `silence_ending_sentence` (text).
   - If no: mark section 3 `[not configured]`.

**Write at end of Phase 1:** spec sections 1 and 3.

### 3.2 Phase 2 — Persona Bundle

**Goal:** populate spec section 2 (5 fields per Doc 1 §6.B.1).

#### 3.2.1 Elicit identity (`prompts.persona`)

Ask: "Who is this bot? Describe identity, role, company context, tone, language posture, and any hard constraints (e.g., 'Hebrew only, never code-switch')."

Draft a `persona` from the user's answer. Show it to them. They confirm or edit.

**Iron rules during this elicitation:**

| Rule | Source | Action |
|---|---|---|
| Persona must articulate identity, role, tone, language. Not "helpful assistant" generic. | §14.3.1 | If user's input is empty/generic, push back: "What specifically is this bot's identity, role, and language? A persona that doesn't articulate these defaults to generic chatbot behavior at runtime." |
| No channel-specific behavior in persona. | §14.3.9 | Catch voice-isms (pacing, pronunciation, interruption, audio cues) and chat-isms (formatting, message length, emojis). Offer to move them to `voiceInstructions` or `chatInstructions`. |
| No per-intent procedural logic in persona. | §14.3.10 | Catch "when validating address, repeat back..." or "after getting available slots, present in order..." — these are per-intent. Offer to move to per-intent `intentInstructions` (Skill 2 will write the actual text). |
| No persistent policy embedded in single intents. | §14.3.13 | Defer this check to Phase 3 boundary, where intents exist to compare against. But ask now: "Are there any policies that apply call-wide (privacy, GDPR, retention, escalation policy)?" — capture into persona directly. |

#### 3.2.2 Elicit channel-specific behavior

For each **active** channel:

- **Voice:** ask about pacing, pronunciation (especially for street names and numbers), interruption handling, audio cues, pauses.
- **Chat:** ask about formatting (markdown vs plain), message length, emoji policy, confirmation patterns.

For each **inactive** channel: emit the templated default automatically per `templates/voice-default.md` or `templates/chat-default.md`. Substitute `[[PERSONA_IDENTITY]]` (extracted from the just-authored persona — first sentence or two establishing identity) and `[[PRIMARY_LANGUAGE]]` (mapped from the language code in section 1 to a human-readable name, e.g., `he-IL` → "Hebrew"). Show the result to the user. Ask: "Accept default or override?"

If user accepts: write to spec preceded by `[default — not user-authored]`.
If user overrides: capture the override; do not include the marker.

#### 3.2.3 Draft `prompts.intentInstructions` (bot-level Opening Behavior)

This is **pre-intent** — what the bot does at the very start of the call, before any specific intent has fired. It contains greeting, routing logic, and disambiguation rules. (Per Doc 1 §14.3.11, this is one of the most-misused fields.)

Ask: "When the call opens, what should the bot do? Greet how, then how does it figure out which intent to route to? What if the caller says something unclear?"

Draft in **Conversation Routines style** (ALL-CAPS headers, numbered steps, IF/ELSE, IRON RULES). Example shape:

```
OPENING BEHAVIOR
1. Greet briefly.
2. Ask what the caller needs.
3. Route based on caller's response:
   - Scheduling → trigger validate_customer_address.
   - Rescheduling → trigger reschedule_existing.
   - General questions → trigger general_inquiry.

IF caller's intent is unclear:
  - Ask once for clarification.
  - If still unclear, route to transfer_to_human.

IRON RULE: Stay in scope. For pricing/billing/technical, route to transfer_to_human.
```

Show the draft. User confirms or edits.

#### 3.2.4 Draft `prompts.openingAnnouncement`

This is the **first audible message** the caller hears (Doc 1 §3). One short utterance.

Ask: "What does the caller hear at the moment of pickup?"

Draft. Show. Confirm.

**Write at end of Phase 2:** spec section 2 (all five fields).

### 3.3 Phase 2 / Phase 3 boundary — Deep Research nudge

Scan the transcript of phases 1-2 for any of the four trigger cues per `trigger-detection-rules.md`.

- **No cue fires:** silent. Proceed directly to Phase 3.
- **Any cue fires:** activate the nudge.

Nudge mechanic:

1. State: "Based on what you've described, external research could meaningfully inform the flow design. I can construct a research query for you to run separately."
2. Construct the query per the template in `trigger-detection-rules.md` — four sections (3 always populated, 1 conditional based on which trigger fired).
3. Present the query.
4. Ask: "Pause here, run this in Deep Research, return with findings — or skip and proceed?"
5. If pause: save state per runtime (single-conversation: emit partial spec + query as message; Claude Code: write `agent-spec.md` partial + `research-query.md`). Append to spec section 7.3: `Deep Research nudge offered (triggers: [list]); user paused for research.`
6. If skip: append to spec section 7.3: `Deep Research nudge offered (triggers: [list]); user skipped.` Proceed to Phase 3.

When user returns from research with findings, incorporate into Phase 3 elicitation. Append to 7.3: `Deep Research findings incorporated.`

### 3.4 Phase 3 — Flow Graph and Intent List

**Goal:** populate spec sections 4, 4.5.1, 4.5.2, 4.5.4 stubs.

#### 3.4.1 Elicit happy path

Ask: "Walk me through the bot's primary success path. What does the caller's first turn look like, what happens next, and how does the call end on the happy path?"

From the answer, sketch an initial intent list (rough names + transitions).

#### 3.4.2 Expand fallbacks

For each non-terminal intent in the sketch:

- "If this intent fails or the caller wants out, where does it go?" — typically `transfer_to_human` (RT=1).
- "If the caller asks something unrelated, what happens?" — typically a catch-all `general_inquiry`.

#### 3.4.3 Per-intent capture

For each intent in the list, capture:

- **Identifier:** snake_case verb_object. Skill 1 enforces strictly per §14.3.8 — reject camelCase, kebab-case, spaces, Title Case. Offer a snake_case alternative; user confirms or proposes another.
- **Display name:** human-readable, often Hebrew if bot is Hebrew-language.
- **Description:** plain language, used by the LLM at runtime for intent recognition.
- **Tool name:** same as identifier.
- **Response Type:** ask: "Does this intent **transfer the call (RT=1)**, **call an external API (RT=2)**, **collect info and continue conversationally (RT=3)**, or **initiate an outbound dial (RT=4)**?"
  - For RT=4: surface the rarity warning per Doc 1 §11.4: "RT=4 (outbound dial) is uncommon. Confirm you actually need to initiate an outbound call from this intent, not transfer the existing call."
- **Transitions out:** ordered list of (target intent, role). Role is "success path" / "fallback" / "escalation".
- **Hard-intent flag:** Skill 1 evaluates per the four criteria below; mark `true` or `false`.

**Hard-intent criteria (decision A — flag if any one applies):**

- RT=2 with more than 3 slots
- Conditional post-execution branching (multiple distinct next-intent paths driven by API response)
- More than 4 outgoing transitions
- Slots requiring complex validation (multi-step, cross-slot dependencies)

#### 3.4.4 Iron rules during Phase 3

| Rule | Source | Action |
|---|---|---|
| Every non-terminal intent has at least one transition to an escalation intent. | §14.3.4 | If missing: "Intent `[name]` has no fallback path. Per Doc 1 §14.3.4, every non-terminal intent must have a transition to (typically) `transfer_to_human`. Add one?" Block until resolved. |
| Naming convention: snake_case verb_object. | §14.3.8 | Reject violations; propose snake_case alternative. |
| Persona's claimed capabilities ⊆ intent set. | §14.3.7 | Now possible to check (intents exist). For each capability claim in `persona`, look for a matching intent. If a claim has no matching intent: "Persona claims `[capability]`, but no intent handles that. Either add an intent or trim the persona." Block until resolved. |

#### 3.4.5 Available-variables interview (4.5.1, 4.5.2, 4.5.4 stubs)

Ask:

- **4.5.1 Call-context variables:** "What platform-supplied variables does your account expose at call start? Common entries: `caller_phone`, `TimeNow`, `caller_name`, `account_id`." If the user can't enumerate: emit defaults `caller_phone` and `TimeNow`, mark section ``.
- **4.5.2 Environment variables:** "Are there any deployment-time secrets you'll reference, like `{{ENV.API_TOKEN}}`?" Capture by name. v1 trusts the user's declaration; no validation that the secret exists.
- **4.5.4 API response shapes:** for each RT=2 intent, ask: "What dotted paths will you reference in the API response announcement? E.g., `available_slots.0.display`, `response.order.status`." Capture per intent. v1 trusts the declared shape; Skill 3 validates `apiResponseAnnouncement` references against this allowlist.

(Section 4.5.3 is auto-derived from section 5 slots — generated in Phase 4 close-out.)

**Write at end of Phase 3:** spec section 4 (intent rows with all structural fields except the per-RT specifics, which Phase 4 fills) and spec section 4.5.1, 4.5.2, 4.5.4.

### 3.5 Phase 4 — Per-intent structural fields

**Goal:** finalize section 4 entries with per-RT structural fields. Create section 5 stubs. Run advisory Mustache pre-check.

#### 3.5.1 Per-RT capture

**For all RTs:** capture slot list — name, ParameterTypeId (per Appendix B), IsRequired, CollectionOrder, OptionList for ENUM.

For unsupported types (number, integer, date, email): emit STRING (ParameterTypeId 1) and flag the slot for Skill 2 to author a `validationPrompt` enforcing format. Note in section 7.3: "Slot `[name]` requires natural-language validation (v1 type fallback: STRING)."

**RT=1:** Layer ID (user-supplied; `` if not known).

**RT=2:**
- URL (user-supplied; `` if not known)
- Method (POST or GET)
- Headers structure (user-described; defaults to `{}`)
- Body structure with Mustache references (user-described)
- API response shape declaration → already captured in 4.5.4
- API silence behavior fields: `silence_duration`, `silence_loops`, `silence_sentence`, `silence_ending_sentence`, `silence_instructions` (text or empty), fallback intent reference

**RT=3:** no structural fields beyond slots. Announcement and post-execution `intentInstructions` are language-heavy — Skill 2 territory.

**RT=4:**

Ask the user "Does this intent dial a number from a slot the caller provided, or a hard-coded number?" and capture per **Dial source**:

- **Dial source = parameter** (slot-driven):
  - `parameter_phone`: the slot identifier on this intent that holds the dialed number
  - `selectdial_option`: literal `"Parameter"`
  - phone1/phone2/phone3: emit empty strings `""`

- **Dial source = static** (hard-coded numbers):
  - `phone1`, `phone2`, `phone3`: up to three E.164 numbers with leading `+`. Tried in order; any unused slot is `""`. Per the global E.164 rule (CLAUDE.md house rules), warn the user that elsewhere in Voicenter `+` is forbidden — RT=4 is the exception.
  - `selectdial_option`: capture the user's literal value (the static-mode value isn't documented as a single fixed string; if user doesn't know, emit the key absent and note in 7.4)
  - `parameter_phone`: emit absent

- **Common (both modes):**
  - `NEXT_VO_ID`: int destination voice-objective id; `` if not known
  - `MAX_DIAL_DURATION`: integer seconds (typical: 60)
  - `record`: bool (typical: `true`)
  - `announcement`: optional string spoken just before transfer
  - `intentLoadingAnnouncement`: optional string spoken while dialing
  - `intentInstructions`: optional post-execution string (Skill 2 may elaborate)
  - `response_success`: obje

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [VoicenterTeam](https://github.com/VoicenterTeam)
- **Source:** [VoicenterTeam/claude-marketplace](https://github.com/VoicenterTeam/claude-marketplace)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-voicenterteam-claude-marketplace-voicenter-bot-spec-designer
- Seller: https://agentstack.voostack.com/s/voicenterteam
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
