Skip to content

Manifest v2

The manifest is the contract between your app and the platform. Both SDKs validate it at load with extra="forbid" / .strict() — unknown fields fail loudly so typos don’t silently disable features.

apiVersion: linkworld.ai/v2
app_id: my-bot
version: 0.1.0
name: My Bot
runtime:
image: ghcr.io/you/my-bot:0.1.0

That’s it. No tools, no scopes, no schedules — your app boots, exposes /health, and idles.

apiVersion: linkworld.ai/v2
app_id: tax-bot
version: 1.2.3
name: Tax Bot
description: Triages inbound emails into tax categories
icon: receipt
category: finance
runtime:
image: ghcr.io/you/tax-bot:1.2.3
port: 8080 # optional, default 8080
resources:
memory_mb: 512 # 64..4096
cpu_cores: 1.0 # 0.1..4
env:
DEBUG: "true"
network:
egress_hosts: # advisory; runtime CNI rules in Phase 3
- api.openai.com
required_scopes:
- mail.send
- files.read
- odoo.read
tools:
- name: classify_invoice
description: Categorize text as invoice/receipt/payroll/other
scopes_required: []
agent_visible: true # optional, default true
lifecycle:
on_install: true
on_uninstall: true
on_inbound: true
on_user_added: false
schedules:
- name: daily-summary
cron: "0 8 * * *"
pricing: # Phase-3 placeholder
model: free

Required. Must be linkworld.ai/v2.

Required. URL-safe slug, immutable across versions. Lowercase alphanumeric + hyphens, 3–64 chars, must start with a letter.

Required. Semantic version (X.Y.Z or X.Y.Z-pre). Each value is a distinct, immutable artifact — bump it on every publish.

Display fields shown in the marketplace and the dev console. name is required; the rest are optional. category is a free-form string (common values: finance, productivity, support, general).

Required. The OCI image the platform pulls when provisioning a container. Must be reachable by the platform’s pull credentials — GHCR public images work out of the box.

Optional, default 8080. Must be 1024–65535.

Optional, default 256. Range 64–4096. Hard cap enforced by the platform.

Optional, default 0.5. Range 0.1–4.0.

Optional. Environment variables baked into the container image at run. Use this for non-secret config (region, debug flags, feature toggles). For secrets, use ctx.secrets.get(...).

Optional. Hostnames your app needs outbound access to. Today this is advisory — runtime CNI enforcement ships in Phase 3.

Required for any app calling platform tools. List every scope your app’s ctx.tools.call(...) paths might need. The tenant must grant these on install. See Scope catalog.

Optional. Custom tools your app exposes to the tenant agent.

FieldRequiredNotes
nameyesLowercase alphanumeric + underscores, 3–64 chars
descriptionyesOne-line; shown to the agent’s planner
scopes_requiredyesSubset of top-level required_scopes
agent_visibleno, default trueIf false, only your own handlers can call it

Optional. Declares which lifecycle hooks your app subscribes to. The SDK refuses to register a handler whose corresponding lifecycle.<hook> isn’t true — fast feedback when you forget to flip the flag.

FieldTypeNotes
on_installboolFires on first activation
on_uninstallboolFires on deactivation
on_inboundboolSubscribes to tenant inbound channel events (opt-in fan-out)
on_user_addedboolFires when a new user joins the tenant
schedules[]listNamed cron entries; minute precision
schedules:
- name: daily-summary
cron: "0 8 * * *"

name is the handle you pass to app.onSchedule(...). cron is standard 5-field cron (minute precision). The platform’s leader-elected scanner ticks every 60s.

Phase-3 placeholder. Today the platform stores it but ignores it.

pricing:
model: free | paid
tier: starter | pro | ... # opaque to the platform
  • Both SDKs use extra="forbid" semantics — a misspelled field rejects the manifest.
  • The platform re-validates on deploy; CI catches most drift before publish.
  • The shared fixture pool at packages/sdk-spec/fixtures/ is the single source of truth for what’s accepted.