Download all docs
apps

App

The shippable unit of Triform — an app assembles elements you already built into one deployable thing, carries it across dev, demo, and live tiers, and gives it a URL the world can reach.

Working with it

Opening a App drills into its contents on the canvas rather than opening a dedicated workbench.

How it appears

The same element type rendered as a definition, a circle instance, and a live workspace card.

Co
type

App

Deployable manifest of elements with environment-specific configuration

appsmanifestdefinition

When to use / not

When to use

  • Bundling a handful of elements — a function, a database, a frontend — into a single thing you can deploy and put behind a URL.
  • Shipping the same assembly through dev → demo → live, where each promotion freezes member versions into an immutable, pinned snapshot.
  • Serving a frontend (spa, ssr, view, three-d) at /{circle}/{app}/live, optionally on your own custom domain with managed DNS and SSL.
  • Giving end-users or anonymous visitors access to a running app without exposing the underlying library elements.

When not to use

  • Orchestrating a sequence of steps with branches, loops, and waits — that is what an automation is for; an app deploys it, it doesn't run the flow.
  • Just grouping related elements for tidiness inside a circle — elements sit flat, so no manifest wrapper is needed until you actually want to deploy.
  • Holding the tenant, schema, or git repo itself — that is the circle the app lives inside.

Topology

A structural container: it holds and organises other elements inside it on the canvas.

Properties

versionstring
Current semantic version (SemVer)
iconstring
Icon identifier or URL
membersarray
Elements referenced from repositories. Items can be slug strings or full member objects.
entrypointsobject
Discriminated entry points into the app, keyed by kind. Each entry binds the app to a member element. Supported kinds: - frontend (spa, ssr, view, three-d) — served at /{circle}/{app}/live - automation (apps/automation) — main automation invoked on deploy/trigger - schedule (io/schedule) — cron-driven trigger - webhook (io/http) — external webhook ingress Set/unset via the polymorphic set_entrypoint / unset_entrypoint ops, or the legacy set_index / unset_index aliases (which target kind:frontend).

Capabilities

Defined for this element
  • Observe

Operations

  • activityGET
  • attachPOST
  • attachmentsGET
  • batch_statsGET
  • buildPOST
  • composePOST
  • contextGET
  • createPOST
  • deleteDELETE
  • demotePOST
  • deployPOST
  • detachPOST
  • disablePOST
  • dnsGET
  • dns_setPUT
  • domainsGET
  • domains_addPOST
  • domains_removeDELETE
  • domains_verifyPOST
  • enablePOST
  • envGET
  • env_deleteDELETE
  • env_setPUT
  • export_bundleGET
  • getGET
  • import_bundlePOST
  • intentionGET
  • promotePOST
  • readmeGET
  • readme_updatePOST
  • referencePOST
  • releasesGET
  • remove-modifierPOST
  • restorePOST
  • rollbackPOST
  • schemaGET
  • set_entrypointPOST
  • set_indexPOST
  • sourceGET
  • source_branchesGET
  • source_promotePOST
  • source_repairPOST
  • source_statusGET
  • source_validatePOST
  • statsGET
  • treeGET
  • unreferencePOST
  • unset_entrypointPOST
  • unset_indexPOST
  • updatePATCH
  • update_metaPATCH
  • versionGET

Composition

Validation rules

  • Project has no members — nothing will be deployed
  • Auto-scaling is disabled — project won't scale under load

App (app)

Category: apps | Form: | Symbol: Co

Deployable manifest of elements with environment-specific configuration

A deployable assembly that references elements from your repositories without owning them. Add elements with the “reference” operation (e.g., ref: “actions/python/my-fn”). Apps support environments: dev, demo, and live. Promote from dev→demo→live to create immutable snapshots with pinned versions. Deleting an app only removes references — the library elements remain. Max 500 members. Note: spec.connections holds canvas diagram edges for visualization only and is not enforced at runtime — elements must be wired via their own API contracts. Common mistake: editing spec.members directly instead of using the reference/unreference operations — direct edits bypass validation and version pinning.

Guide

Deployable manifest that assembles library elements into a runnable unit

What It Does

An app references elements from your repositories without owning them. Add elements with the reference operation, declare data flow connections between them (source:port → target:port), and manage environment-specific configuration across dev, demo, and live tiers. Promote from dev → demo → live to create immutable snapshots with pinned versions. Deleting an app only removes references — the library elements remain.

Element Definition

PropertyValue
Typeapp
Categoryapps
Formmanifest
Symbollayers / #8B5CF6
Residencestructural

Quick Start

# Create an app
POST /api/my-circle/ {"element_type": "app", "slug": "my-app", "name": "My App"}

# Reference elements into the app
POST /api/my-circle/my-app/ops/reference {"ref": "actions/python/my-fn"}
POST /api/my-circle/my-app/ops/reference {"ref": "data/sql/my-db"}

# Deploy
POST /api/my-circle/my-app/ops/deploy

Environments

Apps manage three tiers:

  • dev — auto-updates when referenced elements change
  • demo — promoted from dev, version-pinned snapshot
  • live — promoted from demo, immutable production snapshot
POST /api/my-circle/my-app/ops/promote {"from": "dev", "to": "demo"}

Common Mistakes

  • Editing spec.members directly instead of using reference/unreference operations — direct edits bypass validation and version pinning
  • Max 500 members per app

Workflows

build-ai-app

Build an AI-powered app with an agent, function, and database

  1. Create a function - Library element — write handler code, then reference from this app triform_element(action: "create", element_type: "python", name: "handler", intention: "process requests")
  2. Create a database - The function can read/write via attached data source triform_element(action: "create", element_type: "sql", name: "app-db", intention: "store application data")
  3. Create an agent - Attach platform tools and set a brain triform_element(action: "create", element_type: "triformer", name: "assistant", intention: "AI assistant for this app")
  4. Wire them together - Reference library elements into the app triform_ops(action: "call", slug: "{slug}", operation: "reference", input: { ref: "actions/python/handler" })
  5. Deploy triform_ops(action: "call", slug: "{slug}", operation: "deploy")

build-api

Build an API with HTTP endpoint, function, and database

  1. Create an HTTP connector triform_element(action: "create", element_type: "http", name: "api-endpoint", intention: "receive HTTP requests")
  2. Create a handler function triform_element(action: "create", element_type: "python", name: "api-handler", intention: "process API requests")
  3. Create a database triform_element(action: "create", element_type: "sql", name: "api-db", intention: "store API data")
  4. Wire HTTP → Function → DB - Reference all elements into the app triform_ops(action: "call", slug: "{slug}", operation: "reference", input: { ref: "io/http/api-endpoint" })

Error Recovery

ErrorRecovery guidanceNext actions
connectionConnection diagram edge failed validation. Check that the format is ‘source-slug:port → target-slug:port’. Note: connections are visualization-only and do not wire runtime data paths.
deploymentDeployment failed. Check that all referenced elements are in a valid state.Check member states: triform_ops(action: "call", slug: "{slug}", operation: "get")
referenceElement reference failed. The element may not exist or may not be a containable type.List available elements: triform_element(action: "list")
validationApp validation failed. Check that all members are valid.

Relationships

  • Attaches to: api-token, variable, prompt, rate-limit, auth-policy, validation, alert, evaluator, brand, view, spa, ssr, three-d

Capabilities

  • assembly: References library elements without owning them (manifest form)
  • environment-tiers: Supports dev/demo/live environment tiers with promotion
  • app-transparent-create: Auto-routes element creation to typed repositories
  • activity-scope-members: Activity queries scope to app members
  • container: Contains referenced agents, functions, data, frontend, and integrations
  • deploy: Deploy to environments (dev/demo/live)
  • rollback: Rollback to previous versions
  • domains: Custom domains with SSL
  • environments: Automatic dev/demo/live environment routing
  • promote: Promote configuration between environments

Properties

PropertyTypeDefaultDescription
versionstring"0.1.0"Current semantic version (SemVer)
iconstringIcon identifier or URL
membersarrayElements referenced from repositories. Items can be slug strings or full member objects.
connectionsarrayCanvas diagram edges between referenced elements. Visualization-only — not enforced at runtime. Declaring a connection here does not wire any data path between elements; members must be connected manually via their own API or invocation contracts.
attachmentsobjectPer-element modifier and resource attachments
environmentsobjectPer-environment configuration overrides
entrypointsobjectDiscriminated entry points into the app, keyed by kind. Each entry binds the app to a member element. Supported kinds: - frontend (spa, ssr, view, three-d) — served at /{circle}/{app}/live - automation (apps/automation) — main automation invoked on deploy/trigger - schedule (io/schedule) — cron-driven trigger - webhook (io/http) — external webhook ingress Set/unset via the polymorphic set_entrypoint / unset_entrypoint ops, or the legacy set_index / unset_index aliases (which target kind:frontend).
deploymentobject
scalingobject
resourcesobject
routingobject
input_schemaobjectJSON Schema describing expected input data shape. Used for port compatibility and runtime validation.
output_schemaobjectJSON Schema describing output data shape. Used for port compatibility and runtime validation.

Operations

activity

Get /ops/activity | Auth: Read

Get activity events for this element

Scope depends on element capabilities: individual elements query by element_id, project-form elements with activity-scope-members include member activities, circle-level elements with activity-scope-all query the entire circle. Gracefully returns empty list if activities table is missing (old circles).

attach

Post /ops/attach | Auth: Write

Add an element as a member of this app

Adds an element to this app’s members list. Accepts element slug or element_id (UUID). Validates topology (compound bond rules), detects circular references, and persists the updated members list to git. Optionally pin to a version (@v1, @latest) or set an alias for use in connections. Prefer this operation over direct spec.members edits — PATCH on spec.members is not persisted and will not appear in the tree.

attachments

Get /ops/attachments | Auth: Read

List all modifiers and resources attached to this element

Returns both modifiers (policy enforcement) and resources (data injection) with is_modifier flag to distinguish. Items in the generated MODIFIER_TYPES list are modifiers; everything else is a resource. Includes cascade_policy and version pin info.

batch_stats

Get /ops/batch_stats | Auth: Read

Get per-element statistics for all children of this element

Returns per-child stats plus an aggregate. Most meaningful on compound or manifest form elements (repositories, circles, projects); atoms have no children so the result is an empty children array with a zeroed aggregate. Uses efficient GROUP BY SQL. Weighted averages for eval scores.

build

Post /ops/build | Auth: Admin

Build a new release

Async operation — creates a new versioned release. Version tag is auto-generated if not provided. For frontend members (spa, ssr, view, three-d), triggers the build pipeline. Include a message for release notes. Returns build_id for status polling.

compose

Post /ops/compose | Auth: Execute

Batch add and remove modifiers on this element in a single call

Declarative composition: add modifiers by ref path (slug or path@version) and remove by attachment ID, all in one atomic call on the target element. Each ‘add’ entry resolves the source element, validates topology, attaches with optional priority and cascade policy. Each ‘remove’ entry deletes the attachment row. Returns a summary of what was added and removed. Example: compose({ add: [{ref: “my-prompt”}, {ref: “rate-limit/api@v2”, priority: 50}], remove: [{attachment_id: “uuid”}] })

context

Get /ops/context | Auth: Read

Get connected elements (graph traversal)

Graph traversal showing all connected elements with their relationship type (contains, contained_by, references, referenced_by, attaches, etc.). Use ?depth=N to control traversal depth (default 1) and ?types=actor,data to filter by element types.

create

Post /ops/create | Auth: Write

Create child element

POST to the parent path — element_type goes in the request body, NOT the URL. Both element_type and slug are required and must be non-empty. Name is derived from slug if omitted. Writes to both Git and PostgreSQL. All elements are stored flat under the circle — no intermediate library wrapper rows.

delete

Delete /ops/delete | Auth: Admin

Delete element (soft delete)

Soft delete — sets state to ‘deleted’ but retains the record. Cannot delete elements that have children (has_no_bond precondition) or active runs. Requires admin auth and confirmation.

demote

Post /ops/demote | Auth: Admin

Suspend an environment so its URL stops serving

Sets the target environment’s status to inactive. The /live URL for a suspended environment returns 404 (handle_live honors status). Data is preserved — re-promote (or set status back to active) restores service. Use when you need to take an env offline without losing the pinned snapshot. dev→demo→live precedence still applies; demoting live does not affect demo. Authorization: admin (mirrors promote).

deploy

Post /ops/deploy | Auth: Admin

Deploy project to an environment

Async operation — returns deployment_id immediately, poll status via run_get. Defaults to dev environment if not specified. Optionally deploy a specific version tag (from releases). Resolves all member elements, applies health checks and scaling policies. Requires admin auth.

detach

Post /ops/detach | Auth: Write

Remove a member element from this app

Removes an element from this app’s members list. Accepts element slug or element_id (UUID). Does not delete the element — only removes it from the app’s membership. Updates the members list in git. Any connections referencing this member should be cleaned up separately.

disable

Post /ops/disable | Auth: Admin

Disable element (hides and prevents use)

Idempotent — safe to call on already-disabled elements. Optionally pass a reason string. Disabled elements cannot be invoked or executed. Inverse of enable.

dns

Get /ops/dns | Auth: Read

List DNS records for managed domains

dns_set

Put /ops/dns/{domain} | Auth: Admin

Set DNS records for a domain

domains

Get /ops/domains | Auth: Read

List custom domains

domains_add

Post /ops/domains | Auth: Admin

Add a custom domain

Associates a custom domain with this project. Returns DNS verification instructions (CNAME or TXT record). Domain must be verified via domains_verify before SSL is provisioned. Set primary:true for the main domain. Each domain is scoped to an environment (default: live).

domains_remove

Delete /ops/domains/{domain} | Auth: Admin

Remove a custom domain

domains_verify

Post /ops/domains/{domain}/verify | Auth: Admin

Verify domain ownership

enable

Post /ops/enable | Auth: Admin

Enable element (makes usable and visible)

Idempotent — safe to call on already-enabled elements. Transitions element to ready/enabled state. Cannot enable deleted elements. Inverse of disable.

env

Get /ops/env | Auth: Admin

List environment variables

env_delete

Delete /ops/env/{key} | Auth: Admin

Delete an environment variable

env_set

Put /ops/env | Auth: Admin

Set environment variables

Sets environment variables as key-value pairs. Scope to a specific environment (dev/demo/live) or use “all” (default) to apply everywhere. Variables are available to all project members at runtime. Secret values are masked in env list responses.

export_bundle

Get /ops/export/bundle | Auth: Read

Export element as downloadable git bundle

On non-root-namespace elements, returns a binary git bundle. On root-namespace (circle) elements, dispatch hands off to the circle’s own export_bundle op, which returns a multi-element JSON envelope with one base64 bundle per child element — this is intentional, not an error.

get

Get /ops/get | Auth: Read

Get element details

Element is already resolved by the routing layer — this returns the cached element, not a fresh DB query. Use the path /api/{circle}/{slug} to address elements.

import_bundle

Post /ops/import/bundle | Auth: Write

Import git bundle into element

Accepts a base64-encoded git bundle in the JSON bundle_base64 field. Use overwrite=true to replace existing elements with same slug (default skips duplicates). Imported elements get new UUIDs. Returns counts of imported/skipped elements and any errors.

intention

Get /ops/intention | Auth: Read

Get element intention with full inheritance chain

Returns three levels: direct (this element’s intention), inherited (from category and root), and resolved (final merged intention). Useful for understanding an element’s purpose in context of its hierarchy.

promote

Post /ops/promote | Auth: Write

Promote project from one environment to another

One-way environment progression: dev→demo or demo→live. Creates an immutable snapshot of all member element versions at promotion time, freezing member commits and auto-pinning @latest modifier refs to prevent config drift. Creates a git version tag (promote-{target}-{timestamp}) for rollback. Authorization: dev→demo requires member+ role, demo→live requires admin. Source environment defaults to the tier before target. Returns snapshot array with all promoted elements.

readme

Get /ops/readme | Auth: Read

Get element README.md content

Reads README.md from the element’s git repository. Returns empty content (not an error) if no README exists. Always returns markdown format.

readme_update

Post /ops/readme_update | Auth: Write

Update element README.md content

Creates or overwrites README.md in the element’s git repo. Commits to the draft branch. Content must be provided as a markdown string.

reference

Post /ops/reference | Auth: Write

Add an element reference to this project

Adds an element from a repository to this project’s members list. Use ref as a path (e.g., “actions/python/my-fn”) or provide target_id as UUID. Validates topology (can_reference check), detects circular references, and supports cross-circle refs via published_elements. Optionally pin to a version (“@v4”) or set an alias. Persists the updated members list to git. Prefer this operation over direct spec.members edits.

releases

Get /ops/releases | Auth: Read

List all releases/versions

remove-modifier

Post /ops/remove-modifier | Auth: Execute

Remove an attached modifier from this element by attachment ID

Removes a modifier/resource attachment by its row ID. The ID comes from the attachments or context API. This is the reverse of attach — called on the target element, not the source.

restore

Post /ops/restore | Auth: Admin

Restore element to a specific version

Automatically snapshots the current state before restoring (creates a ‘Before restore to vN’ version entry). Writes restored spec to git as .triform/spec.yaml. Git failures warn but don’t fail the operation — DB state is authoritative. Cannot restore deleted elements.

rollback

Post /ops/rollback | Auth: Admin

Rollback to a previous version

Restores a specific environment to the state captured in a previous git version tag (from promote or build operations). Both environment and version are required. Reads the project spec from the tagged commit and restores member versions to their pinned commits. Creates a new rollback-{env}-{timestamp} tag for audit trail.

schema

Get /ops/schema | Auth: Read

Get element input/output schema (MCP tools/list compatible)

Returns type-level port schemas from the TypeRegistry — not instance-specific overrides. Includes direction (input/output), required flag, and JSON schema per port. Useful for understanding what data an element accepts and produces.

set_entrypoint

Post /ops/set-entrypoint | Auth: Write

Set an entrypoint of any supported kind for this app

Binds the app to a member element by kind. Kinds:

  • frontend → must be a frontend element (spa, ssr, view, three-d); served at /{circle}/{app}/live (same surface as set_index).
  • automation → must be an apps/automation element; the app’s “main” automation invoked on deploy/trigger (runtime wiring is a follow-up).
  • schedule → must be an io/schedule element; cron firing handled by the existing schedule element.
  • webhook → must be an io/http element; external ingress surface.

The runtime validates the bound element’s category matches the kind and writes to spec.entrypoints.{kind}. To clear, use unset_entrypoint with the same kind. set_index / unset_index are back-compat aliases that target kind:frontend.

set_index

Post /ops/set-index | Auth: Write

Set the index frontend for this app

Designates a frontend member as the app’s default — the frontend served when navigating to /{circle}/{app}/live directly. Sets entrypoints.frontend.element to the given member slug. The element must be a frontend type (spa, ssr, view, three-d) and a current member of the app. Use unset_index to clear.

source

Get /ops/source | Auth: Read

Get any file’s content from the element’s git repository

Reads an arbitrary file from the element’s CAS-backed git tree by its relative path. Same store as readme, just generalized. Path safety: rejects .. traversal, leading /, and null bytes. Use this to view main.py for action elements, asset files for SPAs, etc. Returns empty content (not an error) if the file doesn’t exist.

source_branches

Get /ops/source/branches | Auth: Read

List Source branches for this element

Returns the standard draft/demo/live Source branches, their current commits, and promotion relationships. Use GET /api/{element_path}/ops/source/branches.

source_promote

Post /ops/source/promote | Auth: Write

Promote Source branch forward

Promotes draft to demo or demo to live through the generated element op path. Direct Git pushes to demo/live are blocked by Source policy.

source_repair

Post /ops/source/repair | Auth: Write

Inspect or repair the element Source index

Runs Source repair through the element operation path. Defaults to dry_run=true; set dry_run=false only after reviewing a dry-run report.

source_status

Get /ops/source/status | Auth: Read

Get Source control status for this element

Returns the branch-aware clone URL, checkout commands, current draft commit, child source-link count, portable export summary, Source health, warnings, and auth hints for the addressed element. Use the element-first path: GET /api/{element_path}/ops/source/status.

source_validate

Post /ops/source/validate | Auth: Read

Validate Source branch contents

Validates a Source branch before accepting local Git workflow changes or promotion. Defaults to branch=draft and rejects runtime data, generated output, secret material, and unreadable CAS refs.

stats

Get /ops/stats | Auth: Read

Get aggregate statistics for this element

Health status is computed: error if errors_per_day > 5 or success_rate < 0.8, warning if errors_per_day > 0 or success_rate < 0.95. Firing alerts escalate health to error/warning. Default period is ‘day’. Returns runs_per_day, success_rate, avg_duration_ms, and more.

tree

Get /ops/tree | Auth: Read

Get the element’s position in the graph — ancestors, children, references, and subtree statistics

Uses per-circle ElementGraph cache for O(1) lookups. Returns ancestors (containment chain), children (direct), members (references), referenced_by (reverse refs), attachments, and subtree stats. Default depth is 3, max is 10. Pass ?include_metadata=true for name/state on each node.

unreference

Post /ops/unreference | Auth: Write

Remove an element reference from this project

Removes an element reference from this project’s members. Accepts ref (path) or target_id (UUID). Does not delete the library element — only removes the project’s reference to it. Updates the members list in git. Any connections or attachments referencing this element should be cleaned up separately.

unset_entrypoint

Post /ops/unset-entrypoint | Auth: Write

Remove an entrypoint of any supported kind from this app

Clears spec.entrypoints.{kind} so the app no longer has an entrypoint of that kind. Symmetric inverse of set_entrypoint. unset_index is the back-compat alias for kind:frontend.

unset_index

Post /ops/unset-index | Auth: Write

Remove the index frontend from this app

Clears the entrypoints.frontend entry so the app no longer has a default frontend. Navigating to /{circle}/{app}/live will return 404 until a new frontend is set. Back-compat alias for unset_entrypoint kind:frontend — kept so existing callers don’t break when the polymorphic op is preferred.

update

Patch /ops/update | Auth: Write

Update element

Partial update — send only the fields you want to change. spec, name, and intention are all independently optional. spec MUST be a JSON object when present; deep-merged into the existing spec by default. Empty {"spec":{}} preserves existing spec content but still records a new version (no-op for content, not for version state). To clear/replace the entire spec wholesale send {"spec":{...},"deep":false}. List-typed spec fields use replace semantics (the patch list replaces the existing list, no array merging). Coordinates Git + DB writes. Slug cannot be changed after creation.

update_meta

Patch /ops/update_meta | Auth: Write

Update element metadata (lightweight merge — does NOT bump version or snapshot spec)

Shallow JSONB merge into element.meta. Top-level keys in the provided value replace existing meta values; other keys are preserved. Used for UI metadata like canvas positions, panel state, viewer preferences. Wire-shape op_name is update_meta (distinct from update) so SSE subscribers + the cache auto-invalidator can distinguish lightweight metadata changes from spec edits without inspecting the payload. The MutatingElementStore wrapper stamps this op_name on the lifecycle event emitted by update_element_meta storage calls.

version

Get /ops/version | Auth: Read

Get current version or full history

Returns current version by default. Pass ?history=true for full version history (up to ?limit=N, default 50). Versions are backed by the element_versions table. Every spec update creates a new version entry.

Error Codes

CodeClassRetryableDescription
APP_DEPLOY_FAILEDinternalyesApp deployment failed
APP_PROMOTE_FAILEDinternalyesEnvironment promotion failed
APP_REFERENCE_NOT_FOUNDnot_foundnoReferenced element not found in library
APP_CIRCULAR_REFERENCEvalidationnoCircular reference detected in app graph
APP_PORT_MISMATCHvalidationnoConnection port types are incompatible

Observability

Defined for this element

Metrics

  • member_count
  • element_count
  • storage_bytes
  • deploy_count
  • promote_count
  • promote_duration_seconds
  • cascade_resolution_duration_seconds
  • environment_access_total

Events

  • project.created
  • project.updated
  • project.deleted
  • project.deployed
  • project.promoted
  • project.rolled_back
  • project.referenced
  • project.unreferenced

Pricing / cost

Platform default

Operation costs

  • create: free
  • update: free
  • delete: free
  • get: free
  • list: free
  • invoke: 10000 micro-AU
  • tool_use: free