create_storyline
shallowio.agent4/agent4-tenant · Verify this server
Create a storyline draft. After creating, self-check with validate_storyline, then publish_storyline. user_visibility — what the end user sees of their own run: "invisible" (default, no UI), "named" (a banner with the storyline name only), "trail" (banner + read-only view where untaken branches and future steps are redacted grey blocks), "full" (banner with step x/y + full read-only map). `learner_visibility` is the deprecated old name (legacy values hidden/completed_only still accepted and mapped). concurrency — who the progress follows: "user" (default) = progress belongs to the person, all of that user's sessions share one run — fits curricula / onboarding / KYC; "session" = progress belongs to the case, each session gets its own run, a new conversation = a new application — fits licence applications / tickets / per-product flows. Case state goes to the blackboard (travels with the run); facts about the person go to profile dimensions (shared across runs). graph = {"nodes":[Node,...], "edges":[]} (edges are derived from exits, may be left empty). Node = { node_key: stable uuid (unchanged across edits; exits/funnels reference it), title, task (may interpolate {dimension}/{blackboard.key}), type: "task"(default) | "document_review"(visual pre-review of uploads) | "export"(structured report) | "parallel"(parallel branches / AND-join), review: {"checkpoints":[str]} — type=document_review: per-item visual checkpoints, export: {"sections":[str]} — type=export: report sections, parallel: {"branches":[{"key":str,"label":str,"to_node_key":str},...]} — type=parallel: declares required branches, each pointing at a sub-flow entry; the user may do them in any order, the engine tracks completion, and only when ALL are done does the node take its single join exit (put it at exits[0]). A branch sub-flow's last step just exits back to this parallel node — no hand-written completion flags. flags: {"is_entry":bool, "is_terminal":bool}, on_enter_opening: something to say proactively on entry (empty = silent transition), ai_eval_trigger: natural-language condition for when to run AI evaluation (empty = every turn), callback: {"mode":"none"|"backend"|"ui_redirect", "wait_timeout_secs":int, "signal_name":str}, profile_writes: [{"dim":str, "source":"ai"|"rule"|"callback"}] — dimensions this node writes, resources: {"skills":[str],"knowledge_bases":[str],"tools":[str], "resource_mode":"additive"|"replace"}, exits: [Exit,...] (list order = priority; deterministic rule/callback/user_choice are evaluated first, ai last) } Exit = {"kind":..., "label":str, "to_node_key":str, "ai_criteria":str — kind=ai: one natural-language criterion, "user_choice":{"button_text":str} — kind=user_choice, "rule_ast":RuleAst — kind=rule (see below; an AST, not a string), "callback_signal":"done"|"timeout"|"canceled" — kind=callback, "target_storyline_id":str, — kind=goto_storyline "writes":[{"ref":"dim"|"blackboard","key":str,"op":"set"|"inc","value":<num|str|bool>},...]} — deterministic state writes when this exit is taken (this is how profile_writes with source='rule' actually land): set = assign (completion flags / branch flags), inc = increment (loop/retry counters, value defaults to 1). dim writes are constrained by profile_schema. kind ∈ ai|user_choice|rule|callback|goto_storyline. Common control flow composes deterministically (never bet on the LLM): if/else/switch = several rule exits on one node (order = priority); loop/retry = a back-edge + an inc counter in writes + a rule cap gate; AND-join = a parallel node, or hub + completion flags + an "and" rule. RuleAst is one of: comparison {"op":">="|">"|"<="|"<"|"=="|"!=", "left":{"ref":"dim"|"blackboard","key":str}, "right":{"value":<num|str|bool>}} boolean {"op":"and"|"or", "clauses":[RuleAst,...]} profile_schema = dimension definitions, e.g. {"listening":{"type":"int","min":0,"max":100,"visible_to_user":true}}. on_complete="goto_next" requires next_storyline_id (validate/publish reject otherwise). Enrolment (who enters this line, when): is_default=true auto-enrols on first conversation (at most one per agent); allow_agent_enroll=true lets the agent enrol users mid-conversation — in that case ALWAYS write enroll_trigger (one natural-language "enter when", e.g. "the visitor says they want to apply for a loan"), otherwise the agent has no trigger basis and almost never enrols; takes effect after publishing, independent of is_default and manual assignment. See /docs/tenant-guide/storylines.
1 trials · measured 8 days ago
create_storyline scores 100.0/100 on Vouch's measured behaviour index, from 1 real invocation trials against io.agent4/agent4-tenant, measured 25 Aug 2026 under methodology v0.2.0. Every measured component scored 100.
Component breakdown
| Component | Weight | Value |
|---|---|---|
| Reliability | 35% | not applicable |
| Schema integrity | 25% | 100.0 |
| Failure behaviour | 15% | not applicable |
| Latency | 15% | not applicable |
| Concurrency | 10% | not applicable |
Tool details
- Transport
- remote
- Credential class
- self-provisionable
- Category
- Travel & local
- Input schema
- not declared
- Output schema
- not declared
- Side-effect classification
- unclassified
Score history
| Day | Score | Tier | Methodology |
|---|---|---|---|
| 2026-08-25 | 100.0 | shallow | v0.2.0 |
Probe evidence
| Probe | Outcomes |
|---|---|
| schema_integrity | pass: 1 |
Raw request/response logs are not archived yet — the outcome counts above are drawn directly from every recorded trial.
Embed this score
Available for every tool, scored or not — not a verification perk. Always links back to this page.
[](https://vouch.tools/tools/0a5971aa-94cf-4533-8a33-a39d68b43953)