# Scenario and campaign authoring workflow

## Ground the brief in product knowledge

When a brief depends on how Betterstood works, call `elicitra_knowledge_search` before authoring. Search the user's requested locale and narrow to `overview`, `campaigns`, `credits`, `pricing_tiers`, or `use_cases` when useful. Product-reference results can explain concepts and packaging, but they do not grant an entitlement or report the authenticated organization's live account state; use `elicitra_account_info` for the latter.

The search corpus is maintained by Betterstood and is distinct from scenario-owned Knowledge Bases. Public MCP cannot administer or query an organization's scenario documents.

## Create a draft

`scenario_create_draft` accepts a semantic scenario definition, not provider configuration or an internal database object. Supply a new idempotency key for each intended creation. Retrying the identical request with the same key returns the original result for 24 hours.

`definition.assistantName` is an optional 256-character identity label. Leave it
out to use the scenario name. For later changes, send
`set_metadata.assistantName`; send `null` to clear the override. This does not
make the legal notice editable: Betterstood still supplies the AI identity and the
actual recording/transcription statement.

The operation validates the full bundle and checks the organization scenario quota in one transaction. Validation failure never leaves a partial scenario behind.

## Read before updating

Always call `scenario_get` immediately before `scenario_update_draft`. Include the returned `revision` as `expectedRevision` and a fresh idempotency key.

Updates are a closed list of typed operations. They can change scenario metadata and assistant identity, profile, intake, conversation design, fields and ordering, outputs/scoring, analysis style, classifications, and analysis questions. Removals require explicit acknowledgement, except that the explicit `assistantName: null` value is the defined clear operation for that optional label.

If another editor wins the race, Betterstood returns `REVISION_CONFLICT` with the current revision. Read again, reconcile intent, and submit a new operation; do not blindly retry stale input.

If a Studio or Campaign editor already holds the temporary exclusive lease, Betterstood returns `RESOURCE_LOCKED` before producing a write or provider side effect. Do not attempt an early takeover. Wait for the editor to release the resource or for the lease to expire, then read the resource again and explicitly retry with its latest revision and a fresh idempotency key.

## Active campaigns lock MCP writes

Public MCP treats a scenario as editable only while it has no linked `ACTIVE` campaign. Activation and MCP update share the same database lock, so a last-millisecond activation cannot race an update.

When locked, read, review, and export remain available. Continue in the `studioUrl` returned with `SCENARIO_LOCKED`.

## Review before handoff

`scenario_review_draft` returns validation findings, warnings, readiness, and a safe prompt preview. Resolve errors before handing the Studio URL to a human operator.

`scenario_export` returns `elicitra.scenario.v1`. It excludes secrets and provider state and is not a round-trip import promise.

## Create and configure a campaign draft

Call `campaign_create_draft` with a scenario id, name, channel, and unique idempotency key. Creation uses the organization's ordinary non-archived campaign quota. Text Chat accepts a governed budget; Phone Call and Web Call do not.

Read with `campaign_get`, then send its `revision` as `expectedRevision` to `campaign_update_draft`. Updates accept a closed set of operations: `set_scenario`, `set_channel`, `set_intake`, and `set_theme`. Each type can appear at most once. Betterstood applies the complete request atomically in that canonical order and preserves advanced settings the public contract does not own.

Theme input is deliberately constrained to an HTTPS logo (or `null`), brand name, preset font/radius, and known color tokens. Public MCP cannot inject arbitrary CSS.

All campaign writes require DRAFT status. Scenario or channel routing changes are also blocked while non-test interactions are open. A stale revision returns `REVISION_CONFLICT`; editor contention returns `RESOURCE_LOCKED`; a campaign blocked by its lifecycle or interactions returns `CAMPAIGN_LOCKED`. Call `campaign_review_draft` for deterministic, provider-free findings and hand its `editorUrl` to the operator for access configuration and publishing.

## What the agent can never do

- Publish, activate, archive, or delete a scenario or campaign.
- Configure campaign passwords, public access, invite links, or caller numbers.
- Place a live call, run a transcript test, or spend conversation credits.
- Configure provider credentials, voice infrastructure, scenario Knowledge Base storage, or internal policy.
- Read respondent transcripts, recordings, source quotes, or raw model output.
- Remove the active scenario disclaimer or bypass Betterstood guardrails.
