wayai-pro/wayai-skill · Archived

wayai

Configure WayAI hubs, agents, tools, channels, resources, states, evals, outbound, and analytics, plus the Data surface (bases, record types, records, relationships, files, toolsets). Use when: creating or editing a hub or hub config; adding/configuring agents, tools, channels, connections, teams, kanban, states, resources, eval scenarios or journeys, outbound campaigns; running analytics or evals; annotating conversation outcomes; reviewing or editing workspace YAML (hub.yaml, agents/*.yaml, b…

First seen Apr 30, 2026

Installation

$ npx skills add wayai-pro/wayai-skill --skill wayai

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Declared
Codex Declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Declared

Repository health

Default branch main
Open issues 0
Status Archived

Skill metadata

Parsed from SKILL.md frontmatter.

Version6.81.0
Declared agents claude-code cursor codex opencode

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 96,987 B
  • docs SUMMARY.md 1,392 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 154 installs

SKILL.md

WayAI Skill

WayAI is a SaaS platform for AI-powered communication hubs. Each hub combines AI agents and a human team across channels (WhatsApp, Email, Instagram, Telegram, native App). This workspace stores hubs as code — one folder per hub (hub.yaml + agents/*.{yaml,md} + evals/, journeys/, resources/) synced bidirectionally to the platform via the wayai CLI.

Platform is the source of truth. Workspace files are the edit surface — changes flow through files → wayai push → platform. Always wayai pull before editing to catch out-of-band changes.

How to use this skill: this file is the complete concept map — every WayAI primitive is defined here with enough depth to decide what to build and which files to touch. Field-level schemas, per-provider specifics, and mechanics live in references/; each domain section below ends with a pointer to its deep-dive file — open it when you're about to author or debug that domain. Before generating a full hub from scratch, read [references/canonical-example/README.md](references/canonical-example/README.md) once — it shows how the pieces wire together. The full routing table is at the end ([Reference Documentation](#reference-documentation)).

Agent Guidelines

  • At the start of every session, before anything else, get current — every time, even for a quick task: update the CLI, then check whether this skill is stale and refresh it if so. A stale CLI or skill is the most common cause of a step below not working. Run the procedure as written in [Workflow → Existing hub](#existing-hub) steps 1–2 (cold start: [State machine](#state-machine) rows 1–1c), and take the skill-install command from row 1b rather than retyping it — its mkdir -p .claude prefix is load-bearing for Claude Code, and row 1c carries what to do when the install fails
  • Talk like a person, not a manual: the user may be new to WayAI — plain language, no jargon. Keep answers short and to the point; don't explain what they didn't ask about. If they seem stuck or ask what something means, give a one-line answer and move on — don't turn a reply into a tutorial
  • Interface: setup runs on the wayai CLI and workspace files — the only automation surface, and it needs filesystem/shell access (code-harness agents — Claude Code, Codex, Cursor, OpenCode). Drive everything below through it. If you do not have shell access (app-harness agents — Claude Desktop, ChatGPT, etc.), you cannot configure WayAI yourself — hand the work to the person, the same shape as the OAuth connection handoff below (one URL, one action, one return signal): "Open https://app.wayai.pro. Set it up there, or run this with a shell-having agent — the one-prompt install is on https://wayai.pro. Tell me when done." Then keep answering from this skill, and never report config you didn't make
  • Only provide information from this skill, tool descriptions, or reference documentation
  • Do not invent URLs, paths, or steps
  • Hub config flows through files + the wayai CLI; one-time setup (orgs, OAuth) goes through the platform UI. Publishing preview → production is now CLI-capable (wayai publish) or UI
  • Always wayai pull -y before editing — catches out-of-band changes
  • Always wayai push -y immediately after editing — editing and pushing are a single action
  • Never auto-commit — show git diff, wait for user approval

Quick Decision: What Can I Do?

Entity How
Hub settings, agents, agent instructions, tools, kanban, states, resources, evals, journeys, outbound, custom tools CLI (wayai push)
Eval journeys (hub-as-code) — journeys/<slug>.yaml, flat folder CLI (wayai push / wayai pull; pull after first create to sync step ids)
Connections — non-OAuth (Agent providers, STT/TTS, Tool API key, MCP Bearer Token) CLI (auto-created from org credentials)
Connections — OAuth (WhatsApp, Instagram, MCP OAuth) Platform UI
Set/rotate a connection's credential directly (incl. production) CLI (wayai set-connection-credential) or UI
Org credentials — create / rotate / edit CLI (wayai create-credential / wayai update-credential) or UI
Org-level shared resources (org-as-code) CLI (wayai org pull / push / diff)
Bases — schemas, records, relationships, files, toolsets (the Data surface) CLI (wayai bases, wayai records, wayai record-types, …; config-as-code via wayai pull/push bases/<base>) — open [references/bases/README.md](references/bases/README.md) first
Skills sync to providers CLI (wayai sync-skills)
Conversation testing CLI (wayai send-message, wayai conversations, wayai delete-history)
Diagnose why a hub misbehaves (audio/TTS not delivered, agent silent, a tool failing) — check connection/credential health FIRST CLI (wayai alerts) — surfaces active Status & Notices alerts (e.g. an invalid provider key shows as connection_auth 401). Run this before reading code or filing a report
Diagnose an inexplicable agent reply (wrong date, ignored rule, hallucinated value) — don't reason from the transcript; read what the agent actually received (resolved prompt, rendered context, injected timestamps, tool calls) CLI (wayai conversations <id> observability [--message-id <id>]) — run this before editing instructions
Record a post-hoc business outcome on an ended conversation (e.g. customer purchased) as an analytics dimension CLI (wayai conversations <id> annotate --set key=value [--type ...])
Analytics CLI (wayai analytics, wayai analytics query)
Cost / token spend analysis (per message, model, agent, role, or credential) CLI (wayai analytics sql over the message table) — see [references/analytics.md](references/analytics.md#raw-sql--cost-analysis) — data.* paths need an explicit cast to run at all, plus the rules that make sums correct
Eval runs and results CLI (wayai run-eval, wayai eval-results)
List eval scenarios / raw SQL over eval results CLI (wayai evals, wayai evals sql)
Capture production conversation as eval CLI (wayai eval capture <conversation_id>)
Capture production conversation as a journey (full multi-turn transcript) CLI (wayai eval journey capture <conversation_id>)
Stop a running eval session CLI (wayai eval session stop <session_id>)
Delete eval session(s) / run history CLI (wayai eval session delete <session_id>, or --all for every session on the hub)
Bug reporting CLI (wayai report create)
Workspace discovery CLI (wayai list)
Organization — create CLI (wayai org create) or UI
Organization — update, delete UI
Publish/sync a preview to production CLI (wayai publish, alias wayai sync) or UI
Delete hubs UI
Replicate a preview, set/clear a preview's label CLI (wayai replicate / wayai relabel) or UI
Teams, team users, hub users, admins, contact approval UI (Hub → Users tab)
Org tags (create; edit display name/color — the slug is permanent) UI (referenced from hub.yaml tags: by slug)

Entity Hierarchy

Organization                ← CLI (`wayai org create`) or UI
├── Org Credentials         ← CLI (`wayai create-credential`/`update-credential`) or UI — API keys stored once, reused across hubs
├── Org Tags                ← UI — gate which credentials each hub can resolve
├── Org Resources           ← CLI (`wayai org pull/push`) — shared knowledge/skills, fan out to linked hubs
├── Bases                   ← CLI (`wayai bases`) — the Data surface. Org-level, NOT inside a hub (see Bases)
└── Hub                     ← CLI (`wayai create`, or auto-creates on push) or UI; publish/sync via CLI (`wayai publish`) or UI
    ├── Connections         ← auto-created from org credentials on push (non-OAuth); OAuth via UI
    ├── Channels            ← auto-provisioned, never authored (see Channels)
    ├── Agents              ← CLI — `agents/<slug>.yaml` + `<slug>.md`
    │   ├── Tools           ← CLI — native, custom HTTP, MCP, delegation
    │   └── Resource links  ← CLI — `resources:` block in agent YAML
    ├── Kanban statuses     ← CLI — `hub.yaml` (workflow stages for conversations)
    ├── States              ← CLI — `hub.yaml` (JSON-schema data agents read/write)
    ├── Resources           ← CLI — `hub.yaml` + `resources/` folder (knowledge + skills)
    ├── Evals + Journeys    ← CLI — `evals/`, `journeys/`
    ├── Outbound            ← CLI — `hub.yaml` (contacts, lists, schedules)
    └── Teams + Users       ← UI (Hub → Users) — teams, admins, team users, hub users

Setup order: Organization (CLI wayai org create or UI) → Org Credentials (CLI or UI) → Hub (CLI wayai create, or push auto-creates, or UI) → configure agents, tools, connections via CLI.

The wayai connection (native tools) is auto-created when a hub is created — no setup needed.

Hub Types

Type Conversations Channels Use Case
chat ONE per end user WhatsApp, Instagram, Email, Telegram, App Person-centered: support, sales, helpdesk
task MULTIPLE per user App only Task-centered: invoices, inventory, approvals

Decision: external channels (WhatsApp/Instagram/Email/Telegram) needed → chat. Object/task processing → task.

AI Modes & the Conversation Model

Hub-level ai_mode sets what the AI does:

Mode Behavior
pilot AI handles end users autonomously
copilot AI suggests responses to the support team (no channel delivery)
pilot+copilot Switches dynamically based on who currently responds
turned_off AI disabled; humans only

A conversation is the runtime session between an end user and the hub (config entities define behavior; conversations and messages are what they act on):

  • conversation_status: agent (AI handles it) | team (human team handles it) | ended (closed + archived)
  • Status selects the active agent track: status agentPilot track replies to the end user through the channel; status team (with copilot/pilot+copilot mode) → Copilot track drafts suggestions the team sees in /support
  • Track switches: the transfertoteam tool (agent → team) or a team handback in the support UI (team → agent). transfertoagent/consult_agent move between agents within a track
  • Close paths: the agent's closeconversation tool, transitioning into an isTerminalStatus kanban status (any surface — agent or harness tool, team drag-drop, REST), the team UI, or the hub's autocloseinactivedays. Ended conversations are archived and listed in the Ended tab; within conversationretentiondays they still accept post-hoc wayai conversations <id> annotate
  • An agent's reply text is delivered automatically — there is no send-message tool; tools exist for actions beyond replying

Kanban status is orthogonal to all of this: it tracks workflow stage (custom slugs like qualified), not who is responding.

Agent Roles

Role Track Per Hub Description
pilot Pilot 1 Responds to end users autonomously
copilot Copilot 1 Suggests responses to the support team
pilotspecialist / copilotspecialist Both Multiple Delegation target — full transfer via transfertoagent
pilotadvisor / copilotadvisor Both 1 each Advisory input via consult_agent; returns control
monitor Background 1 Observes silently
conversationevaluator / messageevaluator Background 1 each Async quality assessment; excluded from normal routing. Their evaluationvariables feed Analytics; the messageevaluator also scores eval runs
summarizer Background 1 Auto-provisioned with the first pilot/copilot. Rolling JSON summary of older messages, stored as conversation state with reserved slug conversationsummary. Fires async post-turn when effective input tokens cross the summarizer agent's summarizationthresholdtokens (default 120000; see below). Non-background agents see the summary as a <conversationsummary> block and can call expandsummary(sectionid) to fetch original messages. Schema is user-editable but must satisfy the anchor invariant (sections[].id, messageidstart, messageidend)
consultant Track-independent (on-demand) Multiple Consulted by people (and agents) in visible consult threads. Never a pilot/copilot responder, never auto-fired, and never a transfer/advisor target. An advisor advises an AI mid-turn and is invisible; a consultant is consulted by people (and agents) in visible threads. Consult turns bill as normal foreground operations. Configurable today; consult dispatch (tagging a consultant from the support composer) ships in a follow-up

transfertoagent targets any same-track agent — a _specialist or* the entry pilot/copilot, so the pilot can act as a hub-and-spoke router (specialists transfer cross-domain requests back to it for re-dispatch). Cross-track, advisor, consultant, and background roles are never transfer targets.

For role flow, delegation, and settings depth, see [references/agents/roles-and-settings.md](references/agents/roles-and-settings.md).

Handoff context engineering

When a conversation changes hands — transfertoagent or transfertoteam — whoever resumes rebuilds history from scratch, where every prior agent's turns appear as undifferentiated assistant messages and the human team's turns appear unattributed (the model can't tell which turns it authored vs. inherited). The runtime closes that gap automatically — author your agents to cooperate with it:

  • The runtime persists a durable custody marker (This conversation was handed off from X to Y.) on each transfertoagent and transfertoteam, and delivers a one-time continuation note to a receiving agent's first turn (agent→agent only — a team handoff has no AI receiver to brief). You don't write these — so don't put "you were just transferred this conversation" framing in an agent's instructions; it's handled and would double up.
  • Always open each agent's instructions with its identityYou are <Agent Name>, the <role/purpose>…. The runtime reinforces identity at the handoff moment, but the system prompt is the strongest signal and the only one present on every steady-state turn; the custody marker ("…to Y") only lands if the agent knows it is Y.
  • A specialist must do work, not bounce. The runtime blocks delegating back to any agent that already held the conversation earlier in the same turn (A→B→A and longer revisits) — the transfer is refused with an error telling the agent to complete the task, transfer to a different agent, or return control to the user. So don't write a _specialist whose instructions reflexively hand the conversation back to its delegator; it'll just hit the guard. (The chain resets each user turn, so re-routing to an earlier agent on a later* turn is fine.)

Summarizer agent config

The summarizer agent exposes summarizationthresholdtokens (default 120000, min 1000, max 1000000) as a top-level key in agents/summarizer.yaml. Lower it for testing; raise it for very long conversations. The summarizer's connection defaults to the pilot's; edit agents/summarizer.yaml to change its model or system prompt. The conversation_summary state's schema is round-trippable like any other state — extra fields beyond the anchors are allowed but the anchors are load-bearing. (Previously a hub-level hub.yaml setting — relocated to the summarizer agent.)

Connections & Credentials

A connection is a configured instance of a connector (a catalog entry: LLM provider, channel API, tool API, speech service) with its credential, scoped to one hub. An org credential stores the secret once at the organization level; connections reference it by name — raw secrets never enter YAML.

Category Examples
Agent OpenAI, Anthropic, Google AI Studio, OpenRouter, xAI (required for AI)
Channel WhatsApp, Instagram (OAuth — UI only); Resend (email), Telegram (API Key — auto-created)
Tool — Native Wayai (auto-created), External Resources (API Key)
Tool — Custom User-defined HTTP endpoints (API Key, Bearer Token, Basic Auth)
Tool — MCP External MCP servers (Streamable HTTP) — Bearer Token via CLI; OAuth via UI
Speech STT transcribes inbound voice notes (Groq, OpenAI, ElevenLabs); TTS synthesizes spoken replies (OpenAI, Groq, ElevenLabs)

Auto-creation rule: Non-OAuth connections (Agent, STT, TTS, Tool — Custom, Tool — MCP via Bearer Token) are auto-created from matching organization credentials when hub.yaml is pushed. Matching respects org tags (an untagged credential is global — every hub can use it; a tagged credential is visible only to hubs sharing ≥1 of its tags) and credential environment. OAuth connections must be set up in the UI first.

OAuth connection handoff (any time — not just onboarding): OAuth connections (WhatsApp, Instagram, MCP OAuth) can't be created from the CLI — they need a one-time UI flow. Whenever one is needed — first-time setup or later (a new channel, an OAuth MCP server) — hand the user the full-path connections-tab deeplink https://app.wayai.pro/settings/organizations/<orgId>/hubs/<hubId>/connections?connector=<slug> (<orgId>/<hubId> from wayai status --json; <slug>whatsapp, instagram, mcp-server), then wayai pull -y once they're done. The deeplink opens the Connections tab (and highlights the connector if a connection already exists — e.g. re-auth); to create one the user clicks Add Connection, picks the \<Connector\> card, chooses OAuth, and finishes the provider flow. Use this tab form — not /connections/new?connector=…, which takes a connector_id UUID and defaults to the first auth type (MCP → Bearer Token), so it can't reach MCP OAuth (see [navigation.md](references/navigation.md)).

For per-provider setup, credential binding (credential:, no_auth:), tags, and production-credential decoupling, see [references/connections.md](references/connections.md).

Channels

Communication endpoints on a hub — where messages arrive and replies get delivered. Channels are never authored in YAML:

  • app (in-app chat) and system (internal) channels are created automatically with the hub
  • WhatsApp / Instagram / Email (Resend) / Telegram channels are provisioned automatically when their Channel connection is created

Channel uniqueness (phone / page / inbound address) is enforced across production hubs only — a preview can share endpoints with its production, and external channels are testable on previews via #test CODE tester registration (see Hub Environments).

Tools

Capabilities assigned per agent in agents/<slug>.yaml. Remember: replying with text needs no tool — tools are for everything else.

Type Source How
Native Platform built-ins (e.g., updatekanbanstatus, getstate, sendfiles, closeconversation, readfile) Listed by name under tools.native
Custom HTTP endpoints you define Defined under tools.custom with connection, method, path, config
MCP Tools from connected MCP servers Dual-origin — declared per-agent under tools.mcp and/or assigned in the Platform UI. wayai push discovers + assigns in one run; a present mcp key (even []) is authoritative, an omitted one preserves UI-assigned tools. See [native-tools.md](references/agents/native-tools.md#mcp-tools)
Delegation Agent-to-agent (transfertoagent, consultagent, startconsultthread), agent-to-team (transfertoteam), or agent-to-hub (delegatetohub, startconsult_thread) Declared under tools.delegation with target (agent display name, team name, or hub name)

Meta tools (gettoolschema, execute_tool) let agents call tools whose schemas are excluded from the inline list. Full native catalog + params: [references/agents/native-tools.md](references/agents/native-tools.md); custom tool schema: [references/agents/custom-tools.md](references/agents/custom-tools.md); designing which tools/params to expose: [references/agents/tool-principles.md](references/agents/tool-principles.md).

Hub delegation (delegatetohub)

Treats another hub as a consultant. The tool spawns a task conversation in the target hub, and that hub's answer comes back asynchronously as a message in the consult thread the request came from — so the tagging agent's turn ends immediately and must not wait for a result.

- type: hub
  tool: delegate_to_hub
  target: Billing Hub        # a PRODUCTION (published) hub in the same organization
  context_boundary: summary  # instruction | summary | transcript
  • target must be a published (production) hub_type: task hub in the same organization. Production because it matches branching semantics; task because a task hub gives each request its own conversation — a chat hub keeps one conversation per user, so every delegation would pile into a single thread and mix customers. A cross-org, unpublished, or chat-type target fails the push (and, at runtime, the tool call).
  • The target hub must CLOSE the spawned conversation — its close is the completion signal. The request text instructs it to, but a target whose agents can never close (no closeconversation tool, no terminal kanban status) will leave the asker waiting. (An agent-started consult carries an expiry — see startconsult_thread; a team-started hub delegation does not, so give the target hub a way to finish.)
  • context_boundary is a data-sensitivity decision, not a tuning knob. Hubs can differ in team membership and what they may see, so choose deliberately — there is no safe default that fits every pair of hubs:
Value What crosses into the target hub
instruction Only the agent's own request. Nothing from the conversation.
summary (default) The request + the rolling conversation summary.
transcript The request + the full customer transcript.

Internal consult traffic never crosses at any setting, and the model can neither choose the target nor widen the boundary — both are admin config.

  • Only available inside a consult thread, which is where the result is delivered — so assign it to a consultant-role agent. A result arriving after the conversation is closed is dropped (the thread is recorded as cancelledatclose).
  • Configured via CI/YAML only in v1 — the Platform UI's tool "Add" grid omits it until the hub picker and boundary control ship, because attaching it needs both choices above.

Agent-initiated consults (startconsultthread)

Lets a non-background agent put a question to a configured consultant (or partner hub) in a consult thread the support team can see — the third initiator of the one consult substrate, alongside a human tagging a consultant and an agent delegating to a hub.

- type: agent
  tool: start_consult_thread
  target: Billing Expert     # a `consultant`-role agent on this hub
  • The mode follows the target. A same-hub, non-harness consultant answers inside the tool call; a partner hub or a harness-backed consultant answers asynchronously — the asking agent ends its turn ("I'll check and get back to you") and is brought back automatically when the answer lands. A slow sync consult converts to async by itself, so agent instructions must handle "the answer will follow" for any target.
  • Consultant→consultant chains are off by default, and sync-only when enabled — set allowconsultantchain: true on the tool to permit them, against a same-hub, non-harness consultant. monitor, the evaluators, and summarizer can never initiate.
  • Budgets are enforced: consult chain depth, plus cycle refusal in both directions (agent A → B → A inside a hub, hub A → B → A across hubs), a cap per LLM call, and a durable cap per conversation. Every consult turn bills a foreground operation, so these caps are what stop an agent multiplying cost unattended.
  • Nothing stays pending forever: an unanswered consult expires and brings the asker back with a timeout notice; a consult outstanding when the conversation closes is recorded cancelledatclose.
  • A team member posting in an agent-started thread takes it over permanently — the AI is no longer brought back for that thread, and further consults into it return a fixed "taken over by the team" notice.
  • Configured via CI/YAML only in v1, like delegatetohub.

Full parameters and YAML shapes: [references/agents/native-tools.md](references/agents/native-tools.md#startconsultthread).

Kanban & States

Kanban statuses are workflow stages for conversations (visible in support/task views), defined per hub in hub.yaml:

  • Identity: immutable lowercase slug (stored in conversations, analytics, tool params; never renameable) + freely editable display name. Tools accept only slugs (display names ride along as labels) — instructions must reference statuses by slug
  • Behavioral flags: isInitialStatus (exactly one per hub), triggersAgentResponse (transition fires an agent turn), allowsAgentUpdate, isTerminalStatus (entering it closes the conversation; at most one per hub), isSchedulingStatus (+ eventName). Several combinations are mutually exclusive — validated server-side on every write
  • allowednextstatuses — optional transition allowlist, enforced at runtime on every surface, with two exemptions: a non-agent caller reaching the terminal status (the REST surface — board and programmatic alike; agents stay gated), and a re-close of a still-open conversation already sitting in the terminal status — any non-agent REST caller, programmatic ones included, but an agent only when reusing a stored outcome, when the status declares no outcomes, or when the outcome it selects is unrestricted. Omit = unrestricted; [] rejected (use isTerminalStatus)
  • Outcomes — the terminal status only may declare outcomes: [{slug, name, color?, fromstatuses?}] (closing dispositions, e.g. resolved/canceled). fromstatuses is a non-empty source-slug allowlist; omit it to accept the outcome from any source. A genuine terminal Kanban transition requires an eligible outcome and stores its slug for analytics as data.meta.outcome. Agent closes (closeconversation, harness endconversation) are routed through that transition and gated identically. The team Close button (web and mobile) is routed through it too and asks for an outcome first, but as a non-agent caller it keeps the terminal exemption from allowednextstatuses described above; when no outcome is eligible from the conversation's current status it falls back to the bare close rather than stranding it. Inactivity auto-close and POST /:id/close stay outcome-free
  • Followups — per-status timed messages: inactivity (after silence), beforeevent (counting back to the event), inactivityafterevent (the post-visit chase — its first step counts from the event, each later step from the previous nudge) or inactivityafterbeforeevent (the same chase, but starting when one specific beforeevent fires, named by afterfollowupid). The last three require isSchedulingStatus, and none arms unless the conversation carries a scheduledevent_date, supplied per transition and never in status config. With threshold/timeUnit, quiet hours, holiday exclusion
  • Additional context on transition — a triggersAgentResponse status may declare additionalcontextschema (JSON-Schema form the team fills on transition) + additionalinstructions (prose template with {{path.to.field}} / {{additionaldata}} placeholders injected into the triggered turn)
  • Lanes — optional presentational board grouping; no behavioral effect

Full field specs, constraint matrix, warnings, and a complete example: [references/kanban.md](references/kanban.md).

States are JSON-schema data agents read/write during conversations — via native tools (getstate, updatestate, setstatepath, resetstate, all addressing a state by its slug) and the {{state(scope, slug)}} instruction placeholder. Each state has conversation or user scope, a jsonschema, and an optional initial_value (pre-populated virtual record rendered until the first real write; omit to keep state silent until written).

Kanban vs State: kanban tracks workflow progression; state tracks structured data. Both coexist. Schemas and patterns: [references/states.md](references/states.md).

Resources

Knowledge and skills attached to agents. Content lives as real files under resources/<slugified-name>/ (the filesystem is the source of truth for resource content); hub.yaml resources: declares only name/type/description.

Type What Runtime behavior
knowledge (default) Document collections — FAQ, catalogs, policies The linked resources are injected as resources/<slug> mounts into the listfiles native-tool schema at turn time; the agent explores content via listfiles + read_file
skill Versioned capability package — SKILL.md (frontmatter name + description) + optional references/ Injected as a callable tool (default, works on all providers), or run natively in a provider container (usenativeintegration: true, Anthropic/OpenAI only; auto-syncs to the provider on wayai push, wayai sync-skills re-syncs after failures or late-added connections)

Agents link resources in agents/<slug>.yaml under a resources: block (by name, with priority). Org-level resources shared across hubs live in wayai-ws/org/ via wayai org pull/push (push fans out to linked hubs).

File handling (text vs binary, 10 MB cap), skill authoring, execution modes: [references/resources.md](references/resources.md).

Bases (the Data surface)

A base is an org-level data container — the system of record behind your hubs. Hubs hold conversations; bases hold the structured data those conversations act on. Same CLI, same login, same workspace; a separate entity with its own subtree and its own promote verb.

  • Primitives: record type → record, relationship type → relationship, file type → file, plus Actions and toolsets (curated MCP tools an agent calls), triggers and inbound webhooks (change in/out), external sources (back a record type with an external API), and seed fixtures (hermetic eval data)
  • The one rule: config writes (record types, relationship types, file types, triggers, inbound webhooks, Actions, toolsets, seeds) only land on a preview base; data writes work anywhere. Promotion is human-run — surface wayai bases promote <prod> --from <preview> --dry-run and wait
  • Ids are immutable. A base, record type, relationship type, Action or toolset id is its identity — there is no rename, only create-new + migrate. Choose stable lowercase slugs up front
  • Workspace: wayai-ws/bases/<base>/ (base.yaml + one file per entity), reached by wayai pull bases/<base> / wayai push bases/<base>. A pull/push that names targets in both hubs/ and bases/ is refused, never merged
  • Commands: wayai bases plus the top-level records, record-types, relationships, relationship-types, query-relationships, files, file-types, attachments, toolsets, actions, triggers, inbound-webhooks, seed (each takes --base), and wayai bases tokens|secrets|sql|import|batch|providers|report
  • Connecting a hub: today via an ordinary MCP Server connection pointed at a toolset, or as an eval target_base:. Hub-local resources/ files are a different surface and stay hub-local

Open [references/bases/README.md](references/bases/README.md) before doing any base work — it carries the full object model and routes to the per-domain files below. Nothing in this section is enough to author a schema from.

Evals

Test scenarios that run the real agent with its real tools and score the result. The primitives:

  • Scenario (evals/<name>.yaml or evals/<set>/<name>.yaml) — optional multi-turn history, one input, an expected response (text and/or toolcalls), optional evaluatorinstructions. Scored by the hub's message_evaluator agent; a required-but-skipped tool call fails the eval even when the reply text reads fine
  • Scenario set — first-level subfolder (one level only). wayai run-eval runs exactly one set per session, whole or narrowed to chosen scenarios with repeatable --eval (and --runs for chosen repetitions) — the cheap loop when a change touches a few scenarios of a large set
  • Journey (journeys/<slug>.yaml, flat folder) — a stored happy-path transcript that materializes one derived eval per agent turn. The default way to build broad regression coverage: wayai eval journey capture <conversation_id>, then wayai pull (syncs server-minted step ids)
  • Per-run variables + runs: N — reliability is a distribution, not a 1/1 sample; each run resolves {{var(name)}} against its own disjoint row
  • Seed fixture: — for any eval that writes: names a [base](references/bases/README.md) fixture the platform LEASES for the session — resetting it on acquire, clearing it on release — so runs start from a known baseline instead of the last run's residue. One preview base admits one eval session at a time: a second launch is refused with fixturetargetinuse (409) rather than allowed to corrupt the first, and run-eval waits it out by default — as it does fixtureseed_unavailable (409), the base briefly refusing the lease under its own write backpressure
  • Seed initial_state: — pre-populate user-scope WayAI [state](references/states.md) (a recurring-customer record, a saved profile) before input runs, so behavior that depends on memory of prior conversations is testable; isolated + torn down per session like fixture:
  • Capturewayai eval capture <conversation_id> freezes a production conversation's last exchange into a scenario YAML

Good practice for tool-dependent evals: compose journey + fixture: + variables for repeatable, parallel runs, and phrase evaluatorinstructions as functional outcomes, not raw call counts ("one successful booking", not "exactly one bookappointment call") — tools fail transiently, and a correct agent retries. Full YAML shapes, seed-connection setup, run pacing, and authoring/interpreting principles: [references/evals.md](references/evals.md).

Outbound

Proactive messaging — the hub contacts people before they write. Three hub.yaml blocks:

  • outboundcontacts — named contacts with ≥1 channel identifier (phone E.164 / email / instagramsid) + free-form tags
  • outbound_lists — named static collections of contacts (referenced by contact name)
  • outboundschedules — cron expression + timezone + list + channel + execution mode: directmessage (template / free text sent as-is) or agent_trigger (a system message triggers the agent, which opens the conversation naturally using its tools and instructions)

WhatsApp/Instagram delivery is constrained by the 24-hour messaging window (WhatsApp falls back to an approved template; Instagram skips). Inline contacts are practical to ~500 — beyond that, import via UI/API. Shapes, channel rules, limits: [references/outbound.md](references/outbound.md).

Analytics

Every conversation lands in the analytics store with variables from five origins:

Origin Path Set by
System metrics data.system.* Platform — message counts, response times, durations, tokens (~25 metrics)
Agent-defined variables data.variables.* evaluationvariables declared on conversationevaluator / message_evaluator agents
Metadata data.meta.* Platform — subject, kanbanstatus, hubtype
Post-hoc annotations data.annotations.* wayai conversations <id> annotate --set key=value — real business outcomes (purchased, churned) recorded after the conversation ends; correlate predictions vs reality
Eval scores data.eval_scores.* Eval runs only (is_eval = true rows — excluded from production analytics)

Conversation rows are one grain; a second table, message, decomposes each conversation's spend per message (tokens, USD cost, operations) for per-model, per-agent, and per-credential cost analysis.

Query with wayai analytics (summary + per-variable aggregates; --metric, --filter, --period), wayai analytics query (structured: multi-variable, group_by, correlations), wayai analytics sql (raw SQL over conversation and message — the surface for cost analysis), or wayai evals sql (same SQL over eval rows). Defining good variables happens on the evaluator agents ([roles-and-settings.md → Evaluation Variables](references/agents/roles-and-settings.md#evaluation-variables)); filters, aggregations, cost queries, and workflows: [references/analytics.md](references/analytics.md).

Teams, Users & Access

People entities are UI-managed (Hub → Users tab: /settings/organizations/<orgId>/hubs/<hubId>/users), never in YAML:

  • Hub User — the end user the AI talks to (customer/lead/employee). Uses /chat or /task
  • Hub Team User — support team member handling conversations in /support; grouped into Teams (e.g. "Tier 2 Support") that transfertoteam targets by name — an unknown target fails at runtime
  • Hub Admin — full hub config access. Org Owner/Admin — org level (billing, credentials, hubs). Access is per-level, not inherited (an org admin isn't automatically a hub admin)
  • Contact access control — with nonapppermission: requirepermission, unknown channel contacts are held pending (localized auto-reply, overridable via accessrequestmessage) until approved/blocked by the role in accessapproval_role

Hub Environments

Environment Description
preview Default. Editable workspace for configuring and testing
production Read-only. Serves live traffic. Changes flow from preview via publish/sync

Lifecycle:

  1. New hubs start as preview — edit freely. wayai create --label <l> (or wayai push --label <l> on auto-create) names the first preview at creation
  2. Publish (CLI wayai publish, or UI) — first promotion creates a production hub cloned from preview
  3. Sync (CLI wayai publish / alias wayai sync, or UI) — pushes subsequent preview changes to the linked production. The one command auto-detects first-publish vs sync; it confirms by default (shows the preview→production diff) and -y skips the prompt. Promotes the pushed preview state, so wayai push first
  4. Replicate Preview (CLI wayai replicate [hub] --label <l> or UI) — creates a new sibling preview (from a preview or production) for experimentation
  5. Relabel (CLI wayai relabel <label> / --clear, or UI) — set/clear a preview's preview_label (the sibling disambiguator). NOT editable via hub.yaml + push — it's server-owned

Production is read-only — all config mutations flow through preview. Multiple previews can link to the same production (many-to-1). Channel uniqueness is enforced on production only — previews can share phone/email/SID with their production.

WhatsApp/Instagram/Telegram channels can be exercised on a preview before publishing — register a tester via a #test CODE claim code (see references/connections.md → Channel → "Testing a channel on a preview before publishing").

Only preview hubs are editable. wayai pull also writes the linked production hub as a read-only mirror folder (bare slug — no --<label> suffix — with a marker comment in hub.yaml) so the live production config is browsable alongside the preview; wayai push refuses it and it's excluded from auto-select. Use wayai diff --production for a clean preview-vs-production diff.

Hub Settings

Setting Values Default Description
nonapppermission everyone, requirepermission, notallowed everyone Who can reach hub via external channels
timezone IANA timezone For scheduling and display
language en, pt, es en Language for hub-sent text (e.g. the pending-access notice on require_permission channels)
accessapprovalrole admin, team admin Who may approve/block a pending contact: hub admins only, or also support team members
accessrequestmessage string Optional override for the "your access is pending approval" auto-reply (else a localized default by language)
autocloseinactive_days 1180 7 Days of inactivity (no user/team message) before a conversation is force-closed. Every hub has one
conversationretentiondays 130 7 Days an ended conversation's DO stays alive for post-hoc annotate before cleanup (archival still happens at close)
endedindexretention_days 1730 365 Days an ended conversation stays listed in the hub index. Bounds the Ended tab and how far back {{previous_conversations(N)}} reaches
evalretentiondays 03650, or null platform default (90) Days a finished eval session (its runs, results and eval conversations) is kept before retirement. 0 keeps sessions forever. Omitting the field leaves the current value unchanged — write evalretentiondays: null to clear an override and go back to the platform default. Retirement deletes transcripts permanently — eval scores in Analytics survive

First-time setup (cold start)

The user's entry point is wayai.pro, whose onboarding section carries the install command and the example prompt. Once the skill loads (here), this section drives everything from "skill loaded" to "hub responding to test messages." The agent must self-bootstrap from this section alone — returning users (second hub, new project) skip the page.

Always start by running wayai status --json. It returns a single state snapshot. Branch from the result; re-run between steps to confirm progress before moving on (idempotent).

Phrasing templates (use verbatim)

  • Agent action — narrate one line then act, then one-line receipt:

- "Installing the CLI…" → run command → "Done — wayai 2.4.1 installed."

  • User handoff — exactly one URL, one action, one return signal:

- "Open <URL>. Do <one action>. Tell me when done."

State machine

# Detection (from status --json or env) Action
1 CLI missing (wayai --version not found) Agent runs npm i -g @wayai/cli@latest.
1b No harness skill install present at project root (none of <root>/.claude/skills/wayai/SKILL.md, <root>/.opencode/skills/wayai/SKILL.md, <root>/.agents/skills/wayai/SKILL.md exists, where <root> is git rev-parse --show-toplevel or cwd if not in a git repo) If you are Claude Code, first mkdir -p <root>/.claude — the skills installer links Claude Code's .claude/skills/wayai only when .claude/ already exists, else it silently skips it while still printing "symlinked: Claude Code". Then run npx skills add wayai-pro/wayai-skill -y from <root>. After it completes, verify your own harness's path resolves (Claude Code → <root>/.claude/skills/wayai/SKILL.md, following the symlink; other harnesses → <root>/.agents/skills/wayai/SKILL.md). If it resolves, exit (the harness loads the skill next turn). If it doesn't but <root>/.agents/skills/wayai/SKILL.md exists, self-heal: mkdir -p <root>/.claude/skills && ln -sfn ../../.agents/skills/wayai <root>/.claude/skills/wayai, then re-verify. If still nothing, surface the install error and halt — do not silently exit (would loop on re-entry).
1c skill.installed: true, skill.latest is set, and skill.latest is newer than skill.version (CLI nightly check populates skill.latest) Agent runs npx skills add wayai-pro/wayai-skill -y from <root> to refresh the install in place, then exits (the updated skill loads on the next turn). On install failure, surface the error to the user and continue with the existing skill.
2 auth.logged_in: false Agent runs wayai login (opens browser). User handoff: "Open the page that just opened. Sign in or sign up. Tell me when done."
3 auth.logged_in: true, orgs: [] Ask once: "What should we name your organization? (usually your company name)". Then agent runs wayai org create "<name>" and re-runs status --json to pick up the new org. (Manual fallback only if the CLI create errors: open https://app.wayai.pro/settings/organizations/new.)
3b git rev-parse --show-toplevel fails (cwd is not in a git repo) The CLI requires git for workspace detection. Before acting, surface the resolved cwd and confirm with the user — handoff: "I'll initialize a git repo at <cwd>. Confirm or pick a different folder." This prevents accidentally initializing a repo in ~ or another unintended directory. After confirmation, agent runs git init in cwd. Then checks git config --global user.name and git config --global user.email; if either is empty, asks the user once for their name and email and runs git config --global user.name "<name>" / git config --global user.email "<email>". A GitHub remote is not required for the onboarding flow — only set one up later if the user wants the GitOps/CI loop.
4 workspace.scoped: false and reposcopeblocker: null Agent runs wayai init --org <active_org.id> — writes the org binding into wayai-ws/wayai.yaml, the repo's one committed workspace manifest.
4b workspace.scoped: false and reposcopeblocker is set Do NOT run wayai init — it rewrites wayai-ws/wayai.yaml and cannot fix a repo whose two config files disagree. For kind: "conflict", tell the user both organization ids and ask which one this repo belongs to, then delete or correct the root .wayai.yaml. For kind: "invalid", show the named file and its detail and ask the user to fix it. Re-run status --json afterwards.
5 Workspace scoped, hub goal not yet known User handoff: "What should this hub do? Describe the goal, who talks to it, and the main use case."
6 LLM credential missing for chosen provider User handoff: "Paste your OpenAI/Anthropic/Google API key here." Then agent runs wayai create-credential --name <name> --type "Bearer Token" --stdin.
7 Hub needs an OAuth connection (WhatsApp / Instagram / MCP OAuth) Apply the OAuth connection handoff (Connections & Credentials → OAuth connection handoff): send the full-path connections deeplink for the connector, wait for completion, then wayai pull -y. The same handoff applies any time an OAuth connection is needed later, not only here.
8 Prerequisites met Read [references/canonical-example/README.md](references/canonical-example/README.md) once for end-to-end wiring, then generate wayai-ws/hubs/<hub>/hub.yaml + agents/.yaml + agents/.md from the user's description (per-domain refs below for individual shapes), then wayai create -y to create + push the new hub (wayai push -y also auto-creates when the workspace has just this one new folder).
9 Push succeeded Agent runs wayai send-message "Hi" and shows the response. User handoff: "Refine, add tools, or publish?"
10 User confirms publish Agent runs wayai publish — shows the preview→production diff, then confirms (or wayai publish -y to skip the prompt). First publish clones preview → a new production hub; later runs sync. Paid plans only — if the CLI reports publishing requires a paid plan, manual fallback: open the publish deeplink below to upgrade + Publish in the UI.

Deeplinks (canonical URLs — never breadcrumbs)

State URL
3 (org create — manual fallback) https://app.wayai.pro/settings/organizations/new
6 (credential pre-fill) https://app.wayai.pro/settings/organizations/<org_id>/credentials?type=bearer&name=<key-name>&prefill=true
7 (OAuth connection) `https://app.wayai.pro/settings/organizations/<orgid>/hubs/<hubid>/connections?connector=<whatsapp\ instagram\ mcp-server>`
10 (publish — manual fallback) https://app.wayai.pro/settings/organizations/<orgid>/hubs/<hubid>/overview?action=publish

Rules

  • Detect, don't assume — every step starts with a fresh wayai status --json.
  • Agent actions get a one-line receipt; user handoffs get one URL, one action, one return signal.
  • Never invent URLs outside the table above. Never instruct "go to Settings → …" — always a deeplink. For non-onboarding URLs see [references/navigation.md](references/navigation.md).
  • One question at a time during hub scoping (state 5): goal, then channel, then LLM provider.
  • Never auto-commit anything created during onboarding — show git diff and wait for user approval before any commit.

Workflow

Existing hub

  1. Update CLIwayai update (always run before any operation; if the CLI isn't installed yet, bootstrap with npm i -g @wayai/cli@latest)
  2. Update skill if stale — run wayai status --json; if skill.latest is set and newer than skill.version, run npx skills add wayai-pro/wayai-skill -y and exit (the refreshed skill loads on the next turn). Otherwise continue. (Cold-start onboarding runs the same check as state-machine row 1c.)
  3. Pullwayai pull -y (sync local files from platform; catches out-of-band changes)
  4. Read context — read wayai-ws/hubs/<hub>/AGENTS.md for this hub's notes (purpose, decisions, ongoing work); if you're also working a base, read wayai-ws/bases/<base>/AGENTS.md too. AGENTS.md-aware harnesses (Codex, Cursor, OpenCode, Aider) auto-load AGENTS.md natively. Retire an obsolete root bootstrap while you're here — see [Retiring the old root AGENTS.md](#retiring-the-old-root-agentsmd)
  5. Edit — modify hub.yaml, agents/.yaml, agents/.md
  6. Pushwayai push -y (apply to preview hub; auto-pulls server-assigned IDs back)
  7. Testwayai send-message "Hello"
  8. Review — run git diff, ask user to confirm. Never auto-commit. User commits and pushes to main
  9. Go livewayai publish (or the platform UI) when ready: shows the preview→production diff, confirms, then first-publishes (clones preview → new production hub) or syncs subsequent changes. push first — it promotes the pushed preview state, not unpushed local edits

New hub (from scratch)

  1. Credentialswayai create-credential --name "openai-key" --type "Bearer Token" (one-time per org per credential)
  2. Initwayai init (interactive) or wayai init --org <uuid>
  3. Create fileswayai-ws/hubs/<hub>/hub.yaml + agents/.yaml + agents/.md
  4. Createwayai create -y creates the hub, non-OAuth connections, and applies all config (auto-binds the worktree). create <folder> when the workspace has more than one hub folder. (wayai push -y also auto-creates when it resolves to a single new folder; in a multi-hub workspace it requires --hub, so create is the explicit, unambiguous verb.)
  5. Testwayai send-message "Hello"

After the hub exists, follow the existing-hub workflow.

Hub-Folder Memory

wayai-ws/hubs/<hub>/AGENTS.md is the hub-specific memory for this hub — the contextual information the config files (hub.yaml, agents/) can't capture: purpose, key decisions and why, ongoing work, business rules that only apply here, terminology, integration quirks. Read it at the start of every hub-related task. wayai pull/push seed a placeholder AGENTS.md (+ a CLAUDE.md shim) if the folder has none, absence-guarded. AGENTS.md-aware harnesses (Codex, Cursor, OpenCode, Aider) auto-load it natively when the agent's cwd is inside the hub folder.

Maintain it actively:

  • After significant changes (new agent, new tool, business rule update), update AGENTS.md so future sessions inherit the context
  • If a hub folder has no AGENTS.md (or only the seeded placeholder), fill it with what you know — purpose, current agents, recent decisions — and ask the user to confirm or enrich
  • Keep it focused on why decisions were made and what makes this hub different. Don't restate platform mechanics — those live in this skill
  • Record agreed scope in an optional ## Build plan section — that exact heading, an optional Goal: <one sentence> under it, then GitHub task-list items (- [ ] / - [x]), nested at most one level. Keep it under ~30 items; past that, split into phases and archive completed ones into prose above the list. Tick items as they land — an item is done when it's pushed and working, not when the YAML exists. Like the rest of AGENTS.md, it is never synced to the platform
  • Bases get the same treatment. If you're also working with a base, record the context its settings can't capture in the base folder's AGENTS.md under wayai-ws/bases/<base-id>/ (create it + a CLAUDE.md shim if missing)

Overflow content goes into wayai-ws/hubs/<hub>/references/:

  • When AGENTS.md grows past ~200 lines or starts mixing topics, extract the deeper material into focused files under wayai-ws/hubs/<hub>/references/
  • Examples: references/business-rules.md, references/integrations.md, references/glossary.md, references/<api-name>-spec.md, references/<persona>-tone.md
  • Keep AGENTS.md as the always-on entry point with a short pointer to each reference file: e.g., "Detailed pricing rules: references/pricing-rules.md"
  • Hub-folder references/ are not synced to the platform — they're for agent context only, just like AGENTS.md

Retiring the old root AGENTS.md

Older CLIs seeded a repo-root AGENTS.md (plus a CLAUDE.md holding @AGENTS.md) as a session bootstrap: get current, then load this skill. Nothing writes or refreshes it any more, so what it says is frozen at whatever release seeded it while the real procedure keeps moving — a copy that still names an install command or a startup step this skill has since changed will quietly send you down the wrong one. Its content is also entirely redundant now: everything in it is stated here. Retire it the first time you work in a repo that still has one — this is about the repo root only; hub- and base-folder AGENTS.md are memory and stay.

Identify it: the seeded file is titled # Working with WayAI, and its whole body is a "check for updates, then load the WayAI skill" bootstrap plus a few lines on talking to the user — no project-specific content. (A copy from an older release may instead describe two skills to install and load; the WayAI and Data surfaces merged into this one skill, so that one is doubly out of date.) Then:

First, check whether that file is how you got here. Harnesses differ, and this decides the action:

  • You load skills from your own skills directory (Claude Code → .claude/skills/, OpenCode → .opencode/skills/) → the root file is doing nothing for you. Delete it, and delete CLAUDE.md too if it is the one-line @AGENTS.md shim.
  • You auto-load AGENTS.md instead (Codex, Cursor, Aider) → that root file may be the only thing that pointed you at this skill, and deleting it would leave the next session with no entry point. Keep the file and replace the stale bootstrap with a pointer, so nothing is frozen but the hop survives:

```text # Working with WayAI

Load the WayAI skill at the start of every session, before anything else: .agents/skills/wayai/SKILL.md. It holds the real instructions. ```

Either way, if the file also carries your own notes, keep those — replace or delete only the seeded bootstrap part. A root AGENTS.md that is entirely your own content was never the CLI's; leave it alone.

Everything the bootstrap used to say now lives in this skill: the update discipline is in [Agent Guidelines](#agent-guidelines), the procedure in [Workflow → Existing hub](#existing-hub).

Common CLI Commands

wayai update            # Update CLI (run before any operation)
wayai login             # OAuth — or `wayai login --token` for headless/CI
wayai logout            # Sign out and clear stored credentials
wayai whoami            # Show the authenticated identity
wayai org create        # Create a new organization (you become its owner): `wayai org create "<name>"` [--region <r>] [--json]
wayai org pull          # Org-as-code: fetch org-level shared resources → wayai-ws/org/
wayai org push          # Org-as-code: apply local org resources to the platform (fans out to linked hubs); `wayai org diff` previews
wayai create-credential # Create org credential (--name, --type "API Key"|"Bearer Token"|"Basic Auth", --org, --stdin)
wayai update-credential # Rotate/edit an org credential (--name <cred>; --stdin/--secret rotates the secret, --rename, --description, --tag, --environment)
wayai set-connection-credential  # Set a connection's credential directly — --connection <name> + either --org-credential <name> (link) or --field <f> --stdin (raw secret). Works on preview + production (the sanctioned production-credential write)
wayai init              # Scope this repo to an org in wayai-ws/wayai.yaml (interactive — creates an org inline if you have none); --org <uuid> to skip prompt
wayai migrate           # Move a legacy workspace/ + root org/ layout to wayai-ws/, and copy a root .wayai.yaml org binding into wayai-ws/wayai.yaml (the root file is KEPT — older CLIs still need it)
wayai pull              # Pull hub config from platform (-y skips confirmation; auto-binds worktree on first pull). Also writes the linked production hub as a read-only mirror folder
wayai push              # Push local changes (-y skips confirmation; auto-pulls IDs back). Auto-creates a lone new folder; a multi-hub workspace needs --hub or `wayai create`
# `pull`/`push` are ONE verb each, routing by workspace subtree: `hubs/<hub>` (above) or `bases/<base>` (the Data surface).
# The target resolves in this order: the `--hub`/`--base` flag → a positional → the folder you are cd'd into →
#   `wayai-ws/wayai.yaml`'s `default_hub`/`default_base` → the sole folder across both subtrees.
# So in a workspace holding BOTH a hub folder and a base folder, a bare `wayai pull` is refused as ambiguous.
# Name the subtree — `wayai pull bases/crm`, `wayai push hubs/support` — or declare ONE default in wayai-ws/wayai.yaml.
# An invocation naming a target in BOTH subtrees is refused, never merged; run the two it prints, one at a time.
wayai pull bases/<base> # Pull a base's config into wayai-ws/bases/<base>/ (-y skips the overwrite confirm; auto-binds; mirrors a production origin read-only)
wayai push bases/<base> # Push a base folder to its PREVIEW base (--dry-run to stop after the diff; --prune to apply removals). Production is `wayai bases promote`, never push
wayai create [folder]   # Explicitly create a new hub from an idless folder, then push (--label names the preview). The discoverable verb when a workspace has more than one hub folder
wayai diff              # Dry-run diff of local files vs preview (read-only); --production diffs vs the linked production hub
wayai replicate [hub]   # Clone a hub (preview or production) into a new sibling preview; --label <l> names it. Pulls the new preview into its own folder
wayai relabel <label>   # Set a preview hub's label (--clear removes it; --hub to target). Renames the local folder. The server-owned way to change preview_label
wayai publish           # Promote the preview to production (alias: wayai sync). Auto-detects first-publish (clones preview → new production) vs sync (pushes changes to the linked production); shows the preview→production diff and confirms (-y skips). Paid plans only. `wayai push` first — promotes the pushed preview state
wayai use <selector>    # Scope this worktree to a hub or base (UUID, folder name, hubs/<n>, bases/<n>, --hub/--base). Replaces that axis; `--add` widens it instead
wayai unbind [<sel>]    # Drop one entry from the worktree scope; bare, it clears the whole scope (both axes)
wayai send-message      # Test message to a hub (preview or production). -c <id> continues a conversation
                        # `-f, --file <path>` attaches a file (repeatable, max 20, ~7 MB/request) delivered exactly as a real channel does — this is how image/document behaviour gets exercised in the dev loop. Message text is optional when a file is attached (an attachment-only send mirrors a photo with no caption). Images reach the model as a signed URL, not base64
wayai alerts            # Active connection/credential alerts for a hub (Status & Notices). RUN THIS FIRST when a hub misbehaves (audio/TTS not delivered, agent not replying, a tool failing) — an invalid/expired provider key shows as `connection_auth` 401 here instead of forcing a guess from code. --hub <uuid|name>, --json
wayai conversations     # List or inspect conversations (default text view omits message_id — use --json or `observability` to discover ids)
                        # `--status <agent|team|ended>` combines with `--period 7d` / `--from` / `--to`, which bound LAST ACTIVITY: `--status team --to <date>` is the idle human-queue check ("waiting on a person, nothing since <date>"). Without `--status` AND without `--org`/`--all`, a bare `--period`/`--from`/`--to` reads the analytics history instead, which bounds conversation START and covers ended conversations only
                        # `--org <organization_id>` / `--all` list across the hubs `wayai list` enumerates plus the production hubs those name as parents — one command instead of a loop. These always read the live listing (open + ended, windowed on LAST ACTIVITY), with or without `--status`. A production PARENT you cannot read is named as skipped and does not fail the run. A production hub whose PREVIEW you cannot see is not enumerable anywhere, so it is NOT covered and NOT reported at all — reach it with `--hub <id>`. `--limit`/`--offset` are per hub; a hub in scope that refuses is named and the command exits non-zero rather than reporting a smaller queue, and an empty scope is reported as such, never as an empty queue
                        # `wayai conversations <id> observability` — list LLM turns with message_id, latency, tool_calls (assistant turns only)
                        # `wayai conversations <id> observability --message-id <id>` — full record for one turn (prompt, completion, tool calls, tokens; --json for raw)
                        # `wayai conversations <id> annotate --set key=value [--type numeric|categorical|text]` — set a post-hoc business outcome (e.g. customer_purchased=true) on an ended conversation as an analytics dimension; repeat --set for multiple keys (needs the hub within its conversation_retention_days window)
wayai delete-history    # Clear conversation history (testing). Full history (no --conversation-id) ALSO clears the user's user-scoped hub state, so the next send-message is a true cold-open; --conversation-id <id> deletes just one conversation and never touches state
wayai sync-skills       # Sync skills to provider connections; --connection-id <uuid> to scope
wayai sync-mcp          # Re-discover an MCP connection's tools (refresh stale schemas); --connection <name|uuid>; --check reports drift read-only (CI, exit 1 on drift)
wayai analytics         # Summary + per-variable aggregates; --metric, --filter, --period, --json
wayai analytics query   # Structured ClickHouse query (multi-variable, group_by, correlations)
wayai analytics sql     # Raw single-SELECT SQL over `conversation` (one row per conversation) and `message` (per-message tokens/cost/operations — the surface for cost analysis); --schema prints both catalogs + the message-grain rules (`data.*` paths need `toFloat64OrNull(toString(...))` for numerics, `toString(...)` for grouping); --limit, --json
wayai evals             # List eval scenarios for the hub (--enabled / --disabled)
wayai evals sql         # Raw single-SELECT SQL over the hub's eval result rows ("SELECT …"; --schema prints the column + eval-score-path catalog; --limit, --json)
wayai run-eval          # Run a scenario set's enabled evals (sole set by default; --set to pick on multi-set hubs; repeatable --eval <name> runs ONLY those scenarios and --runs 2,6 only those repetitions of one; --pacing conservative|balanced|fast|<ms> to throttle run dispatch; waits inside --timeout for a fixture held by another session or for transient base write backpressure — --no-queue fails fast and --no-wait implies it; exits 1 if --timeout expires with the session still running)
wayai eval-results      # Inspect eval results (--session <id> or --eval <name>; --runs for per-run detail, --json for raw)
wayai eval capture      # Capture production conversation as eval YAML (<conversation_id> [--set <name>])
wayai eval journey capture  # Capture a conversation's FULL transcript as a journey (<conversation_id> [--name <n>]); then `wayai pull` to sync it to journeys/<slug>.yaml
wayai eval session stop     # Cancel a running eval session (<session_id>) — recovery when a run-eval died without cancelling its own session
wayai eval session delete   # Delete an eval session + its run history (<session_id>, or --all for every session on the hub; -y to skip confirm)
# Journeys are hub-as-code: edit journeys/<slug>.yaml and `wayai push` (pull after first create to sync step ids)
wayai list              # List organizations and hubs
wayai status            # Show workspace status
wayai report create     # Create platform bug report (--title, --description, --hub, --conversation, --error). With --hub, auto-attaches the hub's active alerts so triage sees a credential/connection cause up front — check `wayai alerts` yourself first, it's often not a platform bug
wayai report edit       # Amend your own pending report (<id> --title/--description/--error/--steps/--context)
wayai report list       # List your reports (newest first; --status <s>, --json)
wayai report get        # Show a report's status + message thread (<id>, --json)
wayai report accept     # Accept a shipped fix (<id>) → addressed
wayai report contest    # Contest a shipped fix or a dismissal (<id> --reason "...") → back to triage

# Bases — the Data surface. A base is org-level and a separate entity from a hub.
# `use`/`unbind` are local (this worktree's scope file) and DEPRECATED — prefer
# `wayai use bases/<id>` / `wayai unbind bases/<id>`; every other command below
# reaches the platform. Full grammar: references/bases/.
wayai bases list        # List bases (--tag to filter)
wayai bases get <id>    # Show one base
wayai bases create <id> --name "<name>"        # Create (--environment preview|production)
wayai bases update <id> --name/--tags/--timezone/--settings/--integrations
wayai bases rename <id> --name "<name>"        # Display name only — the id/slug is immutable
wayai bases tag <id> --tags a,b                # Replaces the existing tags; names must exist as organization tags
wayai bases delete <id>                        # Tombstone; --purge (preview only) destroys storage
wayai bases create-preview <origin-id> --name "<name>"   # Clone config into a new preview
wayai bases list-previews <origin-id>
wayai bases promote <production-id> --from <preview-id>  # NOT `wayai publish`, which promotes a HUB
wayai bases rollback <production-id> --promotion <id>
wayai bases promotions <production-id>
wayai bases use <base>  # Deprecated alias of `wayai use bases/<id>` (see Worktree scope)
wayai bases unbind      # Deprecated alias — clears only the base axis of the worktree scope
wayai bases tokens|secrets|sql|import|batch|providers|report ...   # namespaced — each names a concept WayAI already owns
                        # (`wayai report` files a PLATFORM bug; `wayai bases report` files a base one)

# Everything INSIDE a base is its own top-level namespace, each taking --base <id>:
wayai records | record-types | relationships | relationship-types | query-relationships
wayai files | file-types | attachments | toolsets | actions | triggers | inbound-webhooks | seed

wayai bases --help (and wayai <namespace> --help) prints the full tree; the grammar for every command above is in [references/bases/](references/bases/README.md). Two collisions worth holding onto: wayai use/wayai unbind maintain one worktree scope covering both hubs and bases (the selector says which — wayai use bases/crm vs wayai use <hub-uuid>), so wayai bases use/wayai bases unbind are deprecated aliases for the base axis alone; and wayai publish promotes a hub while wayai bases promote promotes a base. Hubs and bases are different entities — never substitute one for the other.

Closing the loop on a report you filed. After triage escalates and the fix ships, your report moves to shipped — you'll get an email, and wayai login/wayai status remind you once (or find it with wayai report list --status shipped). Read wayai report get <id> (status + the fixer's note in the thread), then accept if it works or contest --reason "..." if it doesn't. You can also contest a dismissed report you believe is real — it routes back to triage. Contests are bounded (a cap, and triage may mark a dismissal final); past those, contact support.

Most commands accept --hub <uuid|folder> to disambiguate when multiple hubs live in wayai-ws/hubs/.

Worktree scope

Each git checkout (main or linked worktree) carries a scope: a set of hubs and a set of bases, in one file at <git-dir>/wayai-scope (per-checkout, never tracked).

hubs: [11111111-1111-1111-1111-111111111111]
bases: [crm, billing]

It is a routing tripwire, not a concurrency lock (it does not coordinate concurrent edits) and not authorization (grants are the security boundary). It never selects a target either — it only refuses one.

How it fills up. Each axis is seeded independently by the first successful pull/push/create into a checkout whose set for that axis is empty. After that it only grows on purpose: an automatic bind never appends to a non-empty set.

How it is enforced. wayai pull, wayai push, wayai publish and wayai relabel refuse to run against a hub outside a non-empty hubs set; wayai pull bases/<base> and wayai push bases/<base> refuse a base outside a non-empty bases set. Creating a new hub or base in a checkout already scoped on that axis is refused the same way.

Changing it.

wayai use <selector>          # replace that axis with this one target
wayai use --add <selector>    # widen: add one target to that axis
wayai unbind <selector>       # drop one entry
wayai unbind                  # clear the whole scope, both axes

A selector names the axis the same way pull/push do: a bare UUID is a hub, bases/<id> and --base <id> are a base, hubs/<name> and --hub <x> a hub, and a bare folder name is looked up in both subtrees (present in both → refused, never guessed). wayai status shows the current scope; status --json carries it as worktree_scope.

A worktree legitimately scoped to several entities is normal — a base serving several hubs, or delegation wiring hub A to hub B. Widen with --add for those; do not clear the tripwire to get past them.

If push/pull errors with a scope refusal, stop and ask the user before doing anything else. It usually means a prompt was meant for a different worktree. Do not run wayai unbind, wayai use (with or without --add), wayai bases unbind, wayai bases use, or edit the scope file without explicit user instruction in the current session — widening the scope is as much a session-routing action as clearing it, and both change which hub or base the user thinks you're working on.

Repository Structure

.wayai.yaml                              # DEPRECATED org binding — read as a fallback, never written.
                                         #   `wayai migrate` copies it into wayai-ws/wayai.yaml and
                                         #   KEEPS it (older CLIs still require it). Delete it only
                                         #   once every environment running this repo is current.
AGENTS.md / CLAUDE.md                    # STALE if present — an older CLI's root bootstrap; nothing
                                         #   writes or refreshes these now. Delete it, or (on a harness
                                         #   that auto-loads AGENTS.md) replace its body with a pointer
                                         #   to the skill — see "Retiring the old root AGENTS.md".
                                         #   Hub- and base-folder AGENTS.md are memory and are unaffected.
.claude/skills/wayai/                    # Claude Code skill install (provisioned by `npx skills add wayai-pro/wayai-skill -y`)
├── SKILL.md
└── references/                          # On-demand deep-dive references (see index below)
.opencode/skills/wayai/                  # OpenCode skill install (same provisioner; same SKILL.md + references/ layout)
.agents/skills/wayai/                    # Neutral skill install (same provisioner; same SKILL.md + references/ layout)
wayai-ws/                                # All WayAI config-as-code (init creates wayai-ws/hubs/)
├── wayai.yaml                           # Workspace manifest — the repo's ONE committed config file
│                                        #   `organization_id:` / `organization_name:` — which org this
│                                        #   repo is scoped to. Written by `wayai init`; required.
│                                        #   `default_hub:` / `default_base:` — OPTIONAL, which subtree a
│                                        #   bare `wayai pull`/`push` targets. Declare AT MOST ONE:
│                                        #   declaring both is a mixed invocation and is refused.
│                                        #   Write these two by hand — no command creates them.
│                                        #   `wayai init` keeps their VALUES when it rewrites the file,
│                                        #   but YAML comments in it are not preserved.
├── org/                                 # Org-as-code — shared resources (wayai org pull/push)
│   ├── resources.yaml
│   └── resources/<slug>/
├── bases/                               # One folder per preview base (Data surface) — `wayai pull bases/<base>`
│   └── <base-id>/
│       ├── base.yaml                    # Base identity; `wayai use bases/<folder>` reads it
│       ├── record-types/<id>.yaml       # One file per entity, per kind. Secrets are never written
│       ├── relationship-types/<id>.yaml
│       ├── inbound-webhooks/<id>.yaml
│       ├── triggers/<id>.yaml
│       ├── toolsets/<id>.yaml
│       ├── actions/<id>.yaml
│       └── seeds/<id>.yaml
└── hubs/
    └── <hub-slug>--<label>/             # One folder per preview hub (disambiguated)
        ├── hub.yaml                     # Hub config + states + connections + outbound + resources
        ├── agents/
        │   ├── <slug>.yaml              # Agent config (one per agent, slugified name)
        │   └── <slug>.md                # Agent instructions (one per agent)
        ├── evals/                       # Eval scenarios (synced)
        │   ├── <name>.yaml
        │   └── <set>/<name>.yaml
        ├── journeys/                    # Eval journeys (synced; flat folder, one file per journey)
        │   └── <slug>.yaml
        ├── attachments/                 # Eval/journey turn attachment files (synced; hub-root, shared by evals + journeys)
        ├── resources/                   # Knowledge & skill resource files (synced)
        ├── AGENTS.md                    # Hub-specific memory — scaffold seeded on pull/push (NOT synced; fill it in)
        ├── CLAUDE.md                    # Per-hub Claude Code shim — `@AGENTS.md` (seeded if absent, NOT synced)
        └── references/                  # Hub-specific supporting files (NOT synced)
    └── <hub-slug>/                      # Linked production hub: READ-ONLY mirror (bare slug, no --label). Refreshed each pull; never pushed

Preview hub folders use hub-slug--<previewlabel> or hub-slug--<hubid_prefix> for disambiguation; the linked production hub mirrors to the bare hub-slug (no suffix). Existing repos that still use the legacy workspace/ + root org/ layout keep working (the CLI reads either) — run wayai migrate to move to wayai-ws/.

hub.yaml Shape

version: 1
hub_id: "abc-123-def"           # set by `wayai pull` — do not edit
hub_environment: preview         # set by `wayai pull` — do not edit
preview_label: experiment-a      # server-owned, set by `wayai pull` — do not edit (only on previews; sets the hub folder's `--<label>` suffix). Editing here is IGNORED on push (push warns); change it with `wayai relabel <label>` / `--clear`, or set it at creation with `wayai create --label` / `wayai replicate --label` / `wayai push --label`

hub:
  name: Customer Support
  # description: Handles refunds, order status, and billing questions   # optional, human-facing
  hub_type: chat                 # chat | task
  ai_mode: pilot+copilot         # pilot | copilot | pilot+copilot | turned_off
  timezone: America/New_York
  non_app_permission: everyone
  # tags: [retail, vip]          # org tag slug names (create in UI first); gate which org credentials this hub can resolve. Omit to leave unchanged; [] clears. See references/connections.md#organization-tags
  # auto_close_inactive_days: 7  # force-close a conversation after N days of inactivity (see Hub Settings)
  # conversation_retention_days: 7  # keep an ended conversation's DO alive N days for post-hoc `annotate` (see Hub Settings)
  kanban_statuses:               # full field specs + constraints: references/kanban.md
    - slug: new
      name: New
      order: 0
      color: "#22c55e"
      isInitialStatus: true
      allowed_next_statuses: [in_progress, waiting_for_customer, resolved]
    - slug: in_progress
      name: In Progress
      order: 1
      color: "#3b82f6"
      triggersAgentResponse: true   # transition fires an agent turn; can carry additional_context_schema + additional_instructions (see references/kanban.md)
      allowed_next_statuses: [waiting_for_customer, resolved]
    - slug: waiting_for_customer
      name: Waiting for Customer
      order: 2
      color: "#f59e0b"
      allowed_next_statuses: [resolved]
      followups:
        - order: 0
          type: inactivity
          threshold: 30
          timeUnit: minutes
          instructions: "Hi! Just checking in — do you still need help?"
    - slug: resolved
      name: Resolved
      order: 3
      color: "#ef4444"
      isTerminalStatus: true         # at most one terminal status per hub
      outcomes:                      # terminal-transition policy; selected slug → data.meta.outcome
        - { slug: resolved, name: Resolved, color: "#22c55e", from_statuses: [in_progress, waiting_for_customer] }
        - { slug: canceled, name: Canceled, color: "#ef4444" }
        - { slug: abandoned, name: Abandoned, color: "#a0aec0" }

states:
  - id: "state-uuid-789"          # set by pull
    slug: order_tracking           # immutable identifier; auto-derived from name if omitted
    name: order_tracking
    scope: conversation            # conversation | user
    description: Tracks current order
    json_schema:
      type: object
      properties:
        order_id: { type: string }
        status: { type: string, enum: [pending, shipped, delivered] }
    initial_value: { order_id: null, status: null }

connections:
  - name: anthropic
    type: Agent
    service: Anthropic
    # sync_credentials_to_production: true   # default; false keeps production's credential separate (set it via `wayai set-connection-credential`). See references/connections.md#credential-propagation-to-production-sync_credentials_to_production
  - name: my-api-connection
    type: Tool
    service: REST API
  - name: elevenlabs-tts
    type: TTS
    service: ElevenLabs TTS
    settings:            # Per-connection params (voice/model/language, etc.); keys = connector_settings_schema. See references/connections.md
      voiceId: pNInz6obpgDQGcFmaJgB
      modelId: eleven_multilingual_v2

hub.yaml also holds resources:, outboundcontacts:, outboundlists:, outbound_schedules: blocks. See the per-domain references for full schemas.

agents/<slug>.yaml Shape

id: "agent-uuid-123"               # set by pull
name: Pilot Agent
role: pilot
connection: anthropic              # connection display name
# instructions resolved by convention from agents/<slug>.md
# additional_context_template:     # per-turn context, emitted as an <additional_context> tag on the last user message (same {{...}} syntax as instructions). Put high-churn placeholders ({{now()}}, {{state()}}) HERE, not in instructions, to keep the system prompt cache-stable (see references/agents/instructions.md#additional-context-cache-friendly)
# response_format:                 # {schema_name, schema_json} — force structured JSON output instead of free text (see references/agents/roles-and-settings.md#response-format-structured-output)
# enabled: true                    # default; omitted
# include_message_timestamps: false  # default; when true, appends [timestamp, weekday, daypart] to user messages
# previous_conversations_count: 3  # off by default (max 20); this user's N most recent ended conversations, prepended to the FIRST user message and frozen at the first agent turn that uses it. Foreground roles only; `0` clears it (omitting the key on update leaves it as-is); summaries come from the conversation_evaluator (see references/agents/roles-and-settings.md#previous-conversations-context)
settings:
  model: claude-sonnet-5
  max_tokens: 4096
  # temperature (only sampling knob): Sonnet 5 / Opus 4.7+ / Fable strip a non-default value — set it only on Opus 4.6 / Sonnet 4.6 & older
  # reasoning per provider: Anthropic thinking_enabled + effort · OpenAI/OpenRouter/xAI reasoning_effort · Gemini reasoning_level (see roles-and-settings.md)
  # file_handling_mode: no longer changes what the model receives (earlier files are always announced by path, never re-attached); metadata_only still auto-enables read_file. max_attachment_size_mb is inert (see roles-and-settings.md#file-handling-all-llm-connectors)
  # deliver_preamble: true           # default; pre-tool "let me check…" text is delivered as its own message (voice: own TTS clip; ignored on email). false = only the final reply (see roles-and-settings.md#pre-tool-preamble-delivery-all-llm-connectors)
  # copilot_trigger: every_message   # copilot-track only; on_demand suppresses the automatic per-message suggestion — the team pulls one via the "Suggest reply" button (cost/noise lever; see roles-and-settings.md)
tools:
  native:
    - update_kanban_status
    - get_state
    - update_state
  delegation:
    - type: agent
      tool: transfer_to_agent
      target: Specialist - Billing
    - type: team
      tool: transfer_to_team
      target: Tier 2 Support
    # Hub-as-agent: hand a self-contained request to ANOTHER hub in this org.
    # `target` is a PRODUCTION (published) hub name. context_boundary is required
    # reading — see "Hub delegation" below.
    - type: hub
      tool: delegate_to_hub
      target: Billing Hub
      context_boundary: summary   # instruction | summary | transcript
  custom:
    - name: check_order_status
      description: Check order status by email
      method: post
      path: /api/orders/status
      body_format: json
      connection: my-api-connection
      config:
        name: check_order_status
        description: Check order status by email
        parameters:
          type: object
          properties:
            email: { type: string, description: Customer email }
          required: [email]
resources:
  - name: Company FAQ              # links a hub resource by name (see Resources)
    resource_id: "resource-uuid"   # set by pull
    priority: 0

For full agent options (settings per connector, additionalcontexttemplate, responseformat, file handling, native tool params, custom tool fields, composedtools, placeholders), see [references/agents/](references/agents/).

Evaluation variablesconversationevaluator / messageevaluator agents carry an evaluation_variables list (the structured fields they emit per conversation/message, which become data.variables.* in Analytics), round-tripped via pull/push. See [references/agents/roles-and-settings.md](references/agents/roles-and-settings.md#evaluation-variables).

Key Rules

  • Read-only fields: hubid, hubenvironment, id — set by wayai pull, never edit
  • Connection auto-creation: non-OAuth connections in hub.yaml resolve to org credentials by matching service + authentication_type. Use credential field to disambiguate when multiple org credentials share the same auth type. OAuth connections (WhatsApp, Instagram, MCP OAuth) must already exist (UI setup — see OAuth connection handoff) — referenced by name only
  • Production credentials: a connection copies its credential into production on publish/sync by default. Set synccredentialstoproduction: false to keep production's credential separate, then set it directly with wayai set-connection-credential (production is otherwise read-only). See [references/connections.md](references/connections.md#credential-propagation-to-production-synccredentialstoproduction)
  • Org tags: hub.tags (slug names, created in the UI first) gate which org credentials the hub can resolve (matching rule in Connections & Credentials above). A tag's slug is permanent — the UI edits only its display name and color — so these lists never need rewriting. See [references/connections.md](references/connections.md#organization-tags)
  • Tool groups: native (platform built-ins by name), delegation (agent-to-agent/team handoff), custom (HTTP endpoints with connection), mcp (tools from an MCP Server connection, by name + connection — push discovers + assigns; see references/agents/native-tools.md). Designing which params/tools to expose: [references/agents/tool-principles.md](references/agents/tool-principles.md)
  • Names are foreign keys: cross-entity references resolve by display name at push/runtime — agent connection:, delegation target: (agent name or UI-managed team name), agent resources[].name, eval agent:, custom tool connection:. A dangling name fails the push or the runtime call — when renaming anything, update its referrers in the same edit
  • Renaming: change the name field — the stable id ensures it's detected as a rename, not delete + create. For agents, wayai push auto-renames the .yaml and .md files
  • Default omission: fields matching defaults are omitted (e.g., enabled: true, kanban flags default false, excludeHolidays defaults true)
  • Entity matching (sync/diff): id first (stable UUID), then fallback. Exceptions: states match by name (unique per hub regardless of scope); evals match by name + path; native tools by tool_name per agent

Slugification & Entity Matching

Names → URL-safe slugs for filenames:

  1. Lowercase
  2. Normalize accents (NFD + strip diacritics)
  3. Replace non-alphanumeric with -
  4. Collapse consecutive -
  5. Trim leading/trailing -
  6. Limit to 50 chars

Examples: Mario's Pizzamarios-pizza; Suporte Nível 2suporte-nivel-2; Specialist - Billingspecialist-billing.

Editing Agent Instructions

  • File: agents/<slugified-agent-name>.md alongside the corresponding .yaml
  • Always save under wayai-ws/hubs/<hub>/agents/, never /tmp or other paths
  • Always wayai pull before editing to avoid clobbering out-of-band changes
  • Instructions support dynamic placeholders: {{now()}}, {{user_name()}}, {{state()}}, etc. — see [references/agents/instructions.md](references/agents/instructions.md)
  • Structure for reliability: order each .md procedure → guardrails → voice; say what to do (not what to avoid); make every action a named tool call. Structure the prompt so the right action is the first and easiest thing the model can do. Full principles: [references/agents/prompt-principles.md](references/agents/prompt-principles.md)

Reference Documentation

One reference per domain, following the hub navigation order. Concepts live in this file; open the domain's reference when you're about to author its YAML, need field-level schemas or per-provider specifics, or are debugging behavior in that domain.

Domain Reference When to read
Connections [references/connections.md](references/connections.md) Wiring up a channel, agent provider, tool API, or speech connector; credential binding, org tags, production credentials
Agents [references/agents/roles-and-settings.md](references/agents/roles-and-settings.md) Choosing an agent role, delegation flow, connector-specific settings, evaluation variables, response format
Agents [references/agents/native-tools.md](references/agents/native-tools.md) Native tool catalog + parameters, meta tools (gettoolschema, execute_tool), MCP tool assignment
Agents [references/agents/custom-tools.md](references/agents/custom-tools.md) Custom HTTP tool format, OpenAI function schema, composed_tools side effects
Agents [references/agents/tool-principles.md](references/agents/tool-principles.md) Designing a tool surface a fallible agent calls reliably — surface curation > validation > prompt, one-tool-one-intent, fail-loud, guarded atomic ops
Agents [references/agents/instructions.md](references/agents/instructions.md) Placeholder syntax ({{now()}}, {{state()}}, etc.) for agents/<slug>.md
Agents [references/agents/prompt-principles.md](references/agents/prompt-principles.md) Placing & structuring context for reliable execution — context-to-slot-lifetime, cache hygiene, state vs tool-history, flow-before-style, positive framing, voice as its own section
Kanban [references/kanban.md](references/kanban.md) Kanban field specs: flags, transitions, followups, additional-context schema/instructions, lanes, constraint matrix, warnings
States [references/states.md](references/states.md) State JSON Schemas, scope, agent read/write, initial values
Resources [references/resources.md](references/resources.md) Knowledge bases, skill resources, agent linkage, provider sync (wayai sync-skills)
Evals [references/evals.md](references/evals.md) Eval scenario YAML, scenario sets, journeys-as-code, seed fixtures + variables, wayai eval capture / wayai eval journey capture, run pacing, authoring & interpreting principles
Outbound [references/outbound.md](references/outbound.md) Outbound contacts, lists, schedules, channel rules, execution modes
Analytics [references/analytics.md](references/analytics.md) Variable categories/types, filter operators, time analysis, query workflows
Bases [references/bases/README.md](references/bases/README.md) Read first for any base work — the Data object model, the preview/promote rule, and the routing map to the files below
Bases [references/bases/records.md](references/bases/records.md) Record-type schemas, records, the Filter DSL and search, datetimes, partial updates, cancellation/archival, x-fk, relationship types, relationships, batch, bulk import
Bases [references/bases/querying.md](references/bases/querying.md) wayai bases sql — tables, mandatory scoping predicates, JSON subcolumns, the example gallery; x-search tuning and timezone configuration
Bases [references/bases/files.md](references/bases/files.md) File types, versioned path-addressed files, history/diff, S3 mounts, record attachments
Bases [references/bases/config-as-code.md](references/bases/config-as-code.md) wayai-ws/bases/<base>/, subtree routing and mixed-invocation refusal, base.yaml, promote/rollback, eval mode, seed fixtures and leases
Bases [references/bases/integrations.md](references/bases/integrations.md) Canonical-first modeling and the pattern catalog; external sources, inbound webhooks, triggers, provider adapters
Bases [references/bases/toolsets.md](references/bases/toolsets.md) Actions and toolsets (the agent-facing MCP surface), filterablefields/writablefields/base_filter/precondition, base API tokens, base credentials, modeling & tool-design principles
Bases [references/bases/executors.md](references/bases/executors.md) Building the HTTP service that acts on the outside world for a trigger or external source
Canonical example [references/canonical-example/README.md](references/canonical-example/README.md) End-to-end hub showing how hub.yaml + agents/* + resources/ + evals/ + journeys/ cross-reference. Read once before generating a new hub from scratch
Navigation [references/navigation.md](references/navigation.md) App URL surface (/chat, /task, /support, /settings/...), hub-detail tabs, query-string deep links — any time you hand the user a URL
AGENTS.md files [references/agents-md-template.md](references/agents-md-template.md) The per-hub / per-base folder memory pattern — what belongs in an AGENTS.md, and which of the two the CLI seeds