DocsAuthoring templates

Authoring templates

Build one agent. Deploy it to every customer with one command.

Why templates

An agency typically sells the same agent to many customers: an SDR for SaaS startups, an SEO manager for e-commerce, a support triage bot. Templates let you prototype one agent on your own account, snapshot it into a reusable definition, and deploy it to each customer with a single command. Parameters (founder name, domain, brand color) are passed at deploy time so each customer gets a personalized copy.

Note
Template authoring (POST /api/templates, fork, edit) is restricted to agency or @oya.ai accounts. Deploy is open to all. Non-agency users can only deploy to their own account.

Lifecycle

The full happy path:

bash
# 1. Prototype the agent on your own account oya account use --clear # operate as yourself, not a customer # … build the agent in the web app or via CLI … # 2. Snapshot the agent into a new template oya template create \ --name "Acme SDR" \ --category sales \ --display-name "AI SDR for SaaS" \ --from-agent agt_abc123 # 3. (Optional) edit the template content in $EDITOR oya template edit acme-sdr # 4. Pick a customer and deploy oya account use acct_8f3c… oya template deploy acme-sdr \ --input founder_name="Alex" \ --input domain="acme.com" \ --name "Acme Sales Bot" # 5. Wire gateways and deploy oya agent gateway connect <agent_id> slack oya agent deploy <agent_id>

create --from-agent

The fastest way to author a template: point at an existing agent and Oya copies its soul (persona, mission, brand, behavior_rules, welcome_message), every skill attached to it (by skill_id), and every routine (name, prompt, schedule).

bash
oya template create \ --name "Acme SDR" \ --from-agent agt_abc123 \ --include-kb # optional, embeds KB entries into the template

Flags

  • --name: slugified into the template ID. Required only when neither --from-template nor --from-agent supplies one. Collisions get a numeric suffix.
  • --display-name: pretty name shown in the gallery. Defaults to --name.
  • --description, --category, --icon, --color: gallery metadata.
  • --from-template <path|url|->: load a YAML template (path, http(s) URL, or - for stdin).
  • --from-agent <id>: copy soul + skill_ids + routines from an existing agent.
  • --include-kb: with --from-agent, also embed the agent's KB entries (large). Note: KB embedding is preserved in content but not yet auto-replayed on deploy. Customers upload KB after deploy for v1.
  • --restrict-domain example.com: limit who can see the template (repeatable).
Warning
Credentials are stripped from the snapshot. The template references skill IDs only. Every customer wires their own OAuth (Slack, Gmail, etc.) at deploy time.

create --from-template

For full control over the schema, author a YAML file and load it directly. The shape matches the 12 built-in templates at backend/app/templates/catalog/<id>/TEMPLATE.yaml, the same files the Claude Code skill ships as references.

bash
# From a file oya template create --from-template ./acme-sdr.yaml # From stdin cat acme-sdr.yaml | oya template create --from-template - # From a public URL (gist, GitHub raw, etc.) oya template create --from-template https://gist.githubusercontent.com/you/.../acme-sdr.yaml

The canonical YAML schema:

yaml
id: acme-sdr display_name: "Acme SDR" tagline: "Sends 300 personalized cold emails per day" description: | Runs a real outbound motion every weekday for SaaS startups… icon: target category: sales color: "#f59e0b" soul: name: "Acme SDR" chat_model: "gemini/gemini-2.5-flash" persona: | You are an experienced Sales Development Representative… behavior_rules: - "Always personalize outreach with company-specific context." - "Research the lead's company before drafting any message." welcome_message: | I'm your AI SDR. Tell me about your ICP and I'll start sourcing leads. skills: - web-search - fetch-url - brevo - gmail-read - memory gateways_required: - platform: apollo label: "Apollo.io" description: "Search leads and enrich contact data" deploy_inputs: - field: company_name label: "Company Name" type: text required: true placeholder: "Acme Corp" knowledge_base: - filename: "outreach-playbook.md" content: | # SDR Outreach Playbook ## Email Structure routines: - name: "Daily Lead Search" schedule_cron: "0 9 * * 1-5" schedule_human: "every weekday at 9am" prompt: | Populate today's raw candidate pool…
Tip
Working in Claude Code? Read one of the bundled examples first. Try Read ~/.claude/skills/oya/templates/ai-sdr.yaml, then mirror its shape. Every key you see in the example is supported; keys you don't see are not.

fork & edit

Built-in templates (the curated gallery shipped with Oya) are read-only. To customize one, fork it into your account first.

bash
# Fork a built-in oya template fork ai-sdr --name "Acme SDR" # → forked_from: ai-sdr # → new id: acme-sdr # Edit in $EDITOR (YAML round-trip) oya template edit acme-sdr # Print the current YAML (e.g. for piping into git) oya template get acme-sdr

deploy

oya template deploy <template_id> creates a new agent owned by the target account, applies the template's soul, attaches every skill the template references, and installs every routine.

bash
oya template deploy acme-sdr \ --account acct_8f3c… \ --name "Acme Sales Bot" \ --input founder_name="Alex" \ --input domain="acme.com"

Deploy target resolution

The deploy target (which account owns the new agent) resolves in this order:

  • 1. The --account flag, if passed.
  • 2. The active target from `oya account use <id>`, if pinned.
  • 3. Your own account.

deploy_inputs

--input KEY=VALUE values are persisted on the new agent's config.deploy_inputs map. Skill scripts and routines that reference oya_runtime.config() can read them at runtime. Full string interpolation in soul / skills / routines text is a v2 follow-up. Today, deploy_inputs are passed to scripts but not auto-substituted into soul copy.

Visibility restrictions

Set --restrict-domain on create (or edit it later) to limit a template to users from specific email domains. Useful when a template carries customer-specific copy or branded assets.

bash
oya template create \ --name "Acme Internal" \ --from-agent agt_internal \ --restrict-domain acme.com \ --restrict-domain acme-agency.com