Skip to main content

What it does

Emits a single piece of content for the brand: validates persona-intent, drafts to status='queued', and records the action so its 30-day citation and share-of-voice impact can be measured. One atomic emit bundles what create_content_draft, schedule_content, and mark_content_posted do separately — the fine-grained tools remain available for step-by-step human-UI flows. Hub vs spoke is built in: set fan_out_role='hub' on the long-form canonical piece, then call emit_content again with fan_out_role='spoke' and parent_action_id=<hub action id> for each channel adaptation. Spoke outcomes roll up to the hub so you can see “this hub’s Reddit spoke delivered 3× the LinkedIn spoke” as a queryable fact.

When to use

  • The user (or upstream agent) has decided WHAT to post and on WHICH channel.
  • You want one atomic emit that produces a measurable action record.
  • You’re building a hub-spoke fan-out — one hub call, N spoke calls referencing the hub.

When not to use

Inputs

  • persona_id (number, required) — the persona this content targets.
  • intent ('engagement' | 'commercial', required) — engagement builds relationships; commercial drives a buy decision.
  • platform ('linkedin' | 'twitter' | 'reddit' | 'blog' | 'instagram' | 'youtube', required).
  • body (string, 1–8000 chars, required) — the draft. Long-form for blogs; short-form for socials.
  • title (string, ≤200 chars, optional) — defaults to body[:80].
  • source_task_id (number, optional) — anchor: action ticket this responds to. Either this OR from_conversation_id.
  • from_conversation_id (number, optional) — anchor: ingested conversation. Either this OR source_task_id.
  • action_subtype (string, ≤40 chars, optional) — e.g. 'long_form_hub', 'reddit_spoke', 'linkedin_spoke'.
  • fan_out_role ('hub' | 'spoke', optional) — set 'hub' on the canonical piece, 'spoke' on adaptations.
  • parent_action_id (number, optional) — required when fan_out_role='spoke'; the hub action’s id.
  • target_prompt_ids (number[], optional) — tracked prompts this content targets. Scopes 30-day outcome measurement.
  • override_reason (string, ≥8 chars, optional) — bypass block-severity persona-intent violations with an audit record.

Response

On block: isError: true with structuredContent: { status: 'blocked', violations: [...] }. Fix the body or pass override_reason to retry.

Persona-intent validation

Every content emit is persona-scoped — persona_id and intent must be supplied so the validation matrix can fire. Block-severity rules halt the emit unless override_reason ≥ 8 chars is passed (one audit record per blocked rule, with the action tagged validation_status='overridden').

Example

Draft a LinkedIn engagement post for an insider persona, anchored to an action ticket, targeting two prompts: