# Voicenter Bot Json Assembler

> Assembles a fully-detailed Voicenter Agent Spec into Bot JSON wire format — the final mechanical step in the three-skill pipeline. Use this skill when an Agent Spec exists with all section 5 entries marked `[detailed]` and the user wants the deployable JSON. Trigger phrases include "run Skill 3", "assemble the JSON", "emit the bot JSON", "publish the bot", "build the wire-format", "Skill 3 (JSON…

- **Type:** Skill
- **Install:** `agentstack add skill-voicenterteam-claude-marketplace-voicenter-bot-json-assembler`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [VoicenterTeam](https://agentstack.voostack.com/s/voicenterteam)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **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-json-assembler

## Install

```sh
agentstack add skill-voicenterteam-claude-marketplace-voicenter-bot-json-assembler
```

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

## About

# Skill 3 — JSON Assembler & Publish

This skill produces the **deployable Bot JSON** by mechanically projecting a fully-detailed Agent Spec into Voicenter wire-format. It is the third and final skill in the Voicenter Bot generation pipeline:

- **Skill 1 (Agent Spec Designer):** structural design via interview → fills sections 1, 2, 3, 4, 4.5; 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 (this skill):** mechanical assembly of spec → wire-format JSON.

**Operating principle: pure parser, not interpreter.** Skill 3 makes no creative decisions. It does not best-effort interpret ambiguous spec content; if the spec deviates from the strict template, Skill 3 reports a structured parse error and refuses to assemble. The entire skill architecture depends on Skill 3 being deterministic — if Skill 3 interprets, "what JSON does this spec produce?" depends on Skill 3's mood, and the source-of-truth contract dies. Discipline is the design.

The risk vector for this skill is **doing too much**: filling in plausible-looking values for unknowns, smoothing over template deviations, auto-fixing cross-reference violations, deciding RT-specific defaults the spec didn't specify. The anti-list (§8) is the longest and most opinionated section — read it before doing anything else.

---

## 1. Required reading at invocation

Before touching the spec, load context from these references.

| Read | Why |
|---|---|
| Doc 1 §4 — Bot top-level wrapper | Mapping for spec section 1 root fields |
| Doc 1 §5 — `ActiveVersionInfo` envelope | Mapping for version-level fields |
| Doc 1 §6 — The two `AIModelConfig` objects | Top-level vs version-level + `created` payload duplication |
| Doc 1 §7 — Crosswalk: training-doc → JSON paths | Field-name reconciliation reference |
| Doc 1 §8 — `intentList` six parallel collections | The bulk of assembly |
| Doc 1 §9 — `intents[]` 16-field skeleton | Per-intent shape |
| Doc 1 §10 — `IntentParameters` slot definitions | Per-slot shape |
| Doc 1 §11 — `ResponseTypeId` reference (RT=1/2/3/4) | RT-specific Configuration assembly (§4.4) |
| Doc 1 §11.2 — RT=2 pairing rule | Cross-reference check 5 + 6 |
| Doc 1 §12 — `ParameterTypeId` catalog | Slot type emission |
| Doc 1 §13 — Mustache + variable categories | Cross-reference check 7 |
| Doc 1 §15.3 — ID placeholder strategy (Option A) | §4.1 allocation |
| Doc 1 §15.4 — Cross-reference pass spec | §6 — the seven checks |
| Doc 1 §16 — Schema quirks summary | §4.5 + Appendix A |
| Doc 2 §3.7 — Strict-template enforcement | §3 parse rules |
| Doc 2 §6 — Skill 3 architecture | Everything in this file implements this |
| Doc 2 §7.5 — Routing failures back | Appendix B |
| `locked-decisions.md` decision B | Sentinel strategy |
| `locked-decisions.md` decision M | Section 4.5 inventory drives Mustache check |

Also load this file from Skill 1's package:

- `skills/voicenter-bot-spec-designer/model-catalog.md` — required for resolving named catalog entries to `AIModelConfigID` / `AIModelTypeId` and provider model string (§4.2.3).

Skill 3 does **not** load Skill 2's `conversation-routines-style-guide.md`. The style of `validationPrompt` and `intentInstructions` text is Skill 2's concern; Skill 3 emits the text verbatim from the spec, regardless of style.

---

## 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), `agent-spec.md` readable as a file | **Claude Code** |

State the detected runtime. The user can correct.

### 2.2 Read the spec

**Single-conversation:** read backward through the conversation context to find the most recent spec emission. The spec is identifiable by its `## 1. Bot Identity` header and `## 7. Generation Metadata` footer. If both Skill 1 and Skill 2 ran in this conversation, take the most recent (Skill 2's output).

**Claude Code:** read `agent-spec.md` from the workspace (or whatever filename the user references).

**No spec found:** abort with: *"No Agent Spec found. Skill 3 requires a fully-detailed spec produced by Skill 1 → Skill 2. Invoke Skill 1 (Agent Spec Designer) first."*

### 2.3 Pre-flight gates

Two gates run before any assembly work. Both are blocking. Refusal at either gate emits a clear message and halts; no JSON is produced.

#### Gate A — Completeness

Walk section 5. Count entries with status `[structural]` or `[detailed-revisit]`. If the count is greater than zero, refuse:

> Skill 3 will not assemble an incomplete spec. Section 5 has [N] intents still pending: [list with status per intent]. Run **Skill 2 (Intent Detail Author)** to detail them, then re-invoke Skill 3.

The list shows identifier + status (e.g., `validate_customer_address [structural]`, `confirm_appointment [detailed-revisit]`), not detail level.

Cross-check against section 7.5 (which Skill 2 maintains). If 7.5 says zero pending but section 5 has pending entries, that's a Skill 2 bookkeeping bug — surface it: *"Spec inconsistency: section 7.5 reports 0 pending, but section 5 has [N] intents in non-detailed state. Re-run Skill 2 once to refresh, then re-invoke Skill 3."*

#### Gate B — Parseability

Run the strict-template parser (§3) over the spec. The first deviation halts parsing and produces a structured error. No partial assembly.

Parseability is checked before completeness in cases where the file is malformed at the section-header level (e.g., section headers missing entirely) — in that case, Skill 3 cannot even tell which intents are pending. Practical order: try a quick scan for the seven `## N.` section headers first; if they're missing, Gate B fires first. If headers are present, Gate A fires first.

---

## 3. Strict-template parsing

### 3.1 The deterministic parse principle

The Agent Spec template is documented in Doc 2 §3 and codified in Skill 1's `spec-skeleton.md`. Skill 3 reads it as a fixed grammar — no synonyms, no flexibility, no creative tolerance.

Specifically, the parser expects:

- **Section headers exact:** `## 1. Bot Identity`, `## 2. Persona Bundle`, `## 3. Caller Silence Behavior`, `## 4. Intent List (Structural)`, `## 4.5 Available Variables`, `## 5. Intent Details`, `## 6. Cross-References`, `## 7. Generation Metadata`. Exact strings, exact numbering, exact punctuation. `## 1: Bot Identity` is a parse error. `## Bot Identity` is a parse error.
- **Field labels exact:** `**Bot Name:**`, `**Identifier:**`, `**Description:**`, `**Account ID:**`, `**Primary Language:**`, `**Channels Active:**`, `**Voice Name:**`, `**AI Model Config:**`. Bold markdown around the colon-terminated label, exactly as written.
- **Status markers exact:** `[structural]`, `[detailed]`, `[detailed-revisit]`. No synonyms (e.g., `[done]`, `[in progress]`).
- **Unknown markers exact:** `>`, `>`, `[not configured]`. The angle-bracket format is not optional; `(UNKNOWN: ...)` is a parse error.
- **Intent header in section 4:** `### Intent N: ` where N is the 1-based ordinal and identifier is snake_case. The number determines section 4 ordering (used for first-intent start-marker logic in `botIntents[]`).
- **Intent header in section 5:** `### Intent: ` (no ordinal). Identifier matches a section 4 entry.
- **Slot lines in section 4:** numbered list under `**Slots:**` heading, format `[slot_name] — \`ParameterTypeId\` [N], Required [\`true\`|\`false\`], Order [N], OptionList [if ENUM]`.
- **Transition lines in section 4:** numbered list under `**Transitions out:**` heading, each item is a target intent identifier optionally followed by a parenthetical role label (e.g., `1. get_available_slots (success path)`).
- **RT-specific sub-labels in section 4:** for RT=1 intents, `**Layer:**` followed by an integer. For RT=2 intents, `**URL:**`, `**Method:**`, `**Headers:**`, `**Body:**`, and `**API silence behavior:**` (the silence block has six sub-bullets exact: `silence_duration:`, `silence_loops:`, `silence_sentence:`, `silence_ending_sentence:`, `silence_instructions:`, `fallback intent:`). For RT=3 intents, the RT-specific block is empty (no sub-bullets). For RT=4 intents, `**Dial source:**` (`parameter` | `static`), then either `**Parameter phone:**` (slot identifier, when dial-source=parameter) or `**Phone1:** / **Phone2:** / **Phone3:**` (when dial-source=static); plus `**selectdial_option:**`, `**NEXT_VO_ID:**`, `**MAX_DIAL_DURATION:**`, `**Record:**`, optional `**Announcement:**` / `**Loading announcement:**` / `**Post-execution intent instructions:**`, and `**Response success:**` (object with `instructions` key).

### 3.2 Parse error format

When a deviation is detected, halt and emit:

```
Skill 3 parse error.

Location: line  in 
Section: 
Expected: 
Found: 

Fix: 

Skill 3 will not assemble. Re-run Skill 1 patch mode (if the spec was hand-edited or structurally invalid) or fix the deviation manually, then re-invoke Skill 3.
```

The `` is the conversation message reference (single-conv) or the file path (Claude Code). Line numbers are within that source.

Skill 3 does not attempt to interpret around the deviation. It does not emit a partial JSON. It does not flag and continue. One deviation, one error, one halt.

### 3.3 Common deviations and example messages

These are illustrative — the parser is grammar-driven, not pattern-matched, so anything off-grammar surfaces. The examples here are the most common shapes the user will see.

| Deviation | Example error |
|---|---|
| Missing section header | `Expected: '## 4. Intent List (Structural)'. Found: '## Intent List'. Fix: restore the section number and exact heading.` |
| Bold field label punctuation off | `Expected: '**Bot Name:** '. Found: 'Bot Name: '. Fix: wrap the label in bold markdown.` |
| Unknown marker shape wrong | `Expected: '>'. Found: '(UNKNOWN: ...)'. Fix: use angle brackets and the literal token UNKNOWN.` |
| Status marker synonym | `Expected: one of '[structural]', '[detailed]', '[detailed-revisit]'. Found: '[done]'. Fix: re-run Skill 2 to set the canonical marker.` |
| Intent identifier in section 5 has no match in section 4 | `Section 5 entry 'verify_caller_id' has no matching intent in section 4. Fix: re-run Skill 1 patch mode to add the intent or remove the orphan section 5 entry.` |
| Section 4 reference to undeclared transition target | `Intent 'validate_customer_address' transitions to 'get_slots', but no intent 'get_slots' exists in section 4 (closest match: 'get_available_slots'). Fix: re-run Skill 1 patch mode to correct the transition target.` |
| Spec ends mid-intent (truncated upload) | `Section 5 entry 'confirm_appointment' has no closing structure (no following section 6 header). Fix: re-attach the complete spec.` |
| RT-specific sub-label punctuation off | `Expected: '**URL:** '. Found: 'URL: '. Fix: wrap the sub-label in bold markdown.` |

The transition-target check (last two rows) blurs into cross-reference territory — it's caught at parse time because it's a dangling identifier discoverable from sections 4-5 alone, and Skill 3 already has the data. Treating it as a parse error rather than waiting for §15.4 lets the user fix one thing at a time.

---

## 4. Spec-to-wire-format assembly

Run only if both pre-flight gates pass and the parser succeeds. Assembly happens in memory; nothing is emitted until §6 (cross-reference pass) also passes.

### 4.1 ID placeholder allocation

Per Doc 1 §15.3 Option A and Doc 2 §6.5: sequential negative integers, range-coded so the kind of ID is identifiable at a glance.

| ID kind | Placeholder range | Allocation rule |
|---|---|---|
| `BotID` | `-1` | Single value |
| `BotVersionId` | `-2` | Single value |
| `IntentCategoryId` | `-3` | Single default category |
| `IntentId` | `-10, -11, -12, ...` | One per intent in section 4 ordering (Intent 1 → -10, Intent 2 → -11, ...) |
| `BotIntentID` | `-100, -101, -102, ...` | One per intent, same ordering |
| `ParameterId` | `-1000, -1001, -1002, ...` | One per slot, walked intent-by-intent then slot-by-slot |

`AccountID` is **user-supplied** (spec section 1). If the spec marks ``, emit the sentinel `-999` per §4.6.

`AIModelConfigID` and `AIModelTypeId` come from spec section 1 + the model catalog (§4.2.3). If the catalog has TODO placeholders or the spec marks them unknown, emit `-999` sentinels.

**Allocation procedure:**

1. Walk section 4 in order. For each intent: assign `IntentId` from the `-10` series and `BotIntentID` from the `-100` series. Cache the mapping ` → (IntentId, BotIntentID)`.
2. Within each intent's section 5 entry, walk slots in `Order` value. For each slot: assign `ParameterId` from the `-1000` series. Cache the mapping `. → ParameterId`.
3. Emit `BotID = -1`, `BotVersionId = -2`, `IntentCategoryId = -3` as fixed values.

The cached mappings are used in §4.3 wherever an ID is referenced (transition rows, parameter parent-ID, api-silence relations, botIntents references).

The numerical ranges are wide so a human reading the JSON can identify what kind of ID a placeholder represents at a glance. Real platform-assigned IDs after import will be positive integers, so there's no collision risk on re-export.

### 4.2 Top-level wrapper and version envelope

#### 4.2.1 Top-level fields (spec section 1 → root)

| Spec field | Wire-format path | Source |
|---|---|---|
| Bot Name | `.Name` | Direct copy |
| Description | `.Description` | Direct copy |
| (allocated) | `.BotID` | `-1` |
| Account ID | `.AccountID` | Direct copy, or `-999` sentinel if `` |
| (constant) | `.BotStatusId` | `1` (per Doc 1 §4) |
| (constant) | `.BotLanguages` | `[]` (preserved per §16, even though the bot has a language elsewhere) |
| (generated) | `.CreatedDate` | ISO timestamp at assembly time, format `"YYYY-MM-DD HH:MM:SS"` |
| (constant) | `.ModifiedDate` | `null` (no modifications yet) |
| (resolved) | `.AiModelConfig` | §4.2.3 below |
| (assembled) | `.ActiveVersionInfo` | §4.2.2 below |
| (assembled) | `.intentList` | §4.3 below |

#### 4.2.2 `ActiveVersionInfo` envelope

| Wire-format path | Value |
|---|---|
| `BotVersionId` | `-2` (placeholder) |
| `VersionNumber` | `"0.0.1"` (per Doc 1 §5; v1 always emits this) |
| `BotVersionStatusId` | `3` (per Doc 1 §5) |
| `IsActive` | `1` |
| `Description` | `""` (matches both production samples) |
| `CreatedDate` | Same ISO timestamp as root |
| `ModifiedDate` | `null` |
| `SystemPrompt` | `""` (preserved per §16; NOT the same as the bot's system prompt, which lives in `AIModelConfig.prompts`) |
| `AIModelConfigId` | Same value as `.AiModelConfig.AIModelConfigID` (mirror) |
| `AIModelConfig` | §4.2.3 + 4.2.4 + 4.2.5 below |

#### 4.2.3 The two `AIModelConfig` objects

Doc 1 §6 defines two distinct objects with confusingly similar names. Both must be emitted, and their `created` payloads must be **identical**.

**Top-level `.AiModelConfig`** (catalog reference, Doc 1 §6.A):

| Field | Source |
|---|---|
| `AIModelConfigID` | From `model-catalog.md` if spec section 1 names a catalog entry; from spec if `raw: ID=N, TypeID=M`; `-999` if unknown |
| `Name` | From `model-catalog.md` "Display name"; `` if raw override |
| `Description` | From `model-catalog.md` "Notes" if available; `null` otherwise |
| `BaseUrl` | `null` (matches both production samples) |
| `AIModelTypeId` | Same source rule as `AIModelConfigID` |
| `Type` | `{ "AIModelTypeId": , "Name": , "Description": null }` — type name is the catalog entry's display name; `null` if unknown |
| `created` | The runtime LLM API payload; see §4.2.4 below |

**Version-level `.ActiveVersionInfo.AIModelConfig`** (runtime config, Doc 1 §6.B):

| Field | Source |
|---|---|
| `prompts` | §4.2.4 below |
| `created` | **Identical** to `.AiModelConfig.created` (same object; per §16 quirk, both are required) |
| `silence_behaviour` | §4.2.5 below; omitted entirely if spec sect

…

## 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-json-assembler
- 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%.
