Skip to main content
A Truffle app is a containerized Python program that runs on your Truffle and extends what the on-device agent can do. Apps come in three shapes: You pick the shape by including a foreground, background, or both sections in your truffile.yaml. The supported development loop is intentionally CLI-first: scaffold locally, validate locally, dry-run the deploy plan, then deploy to a connected device. The bundled examples live under truffile/app-store/ in the truffile repo. Treat them as reference implementations:

The SDK import surface

App code imports everything it needs from truffile.app_runtime. This is the module that ships with the truffile package when you pip install truffile.
The source lives in truffile/app_runtime/ in the repo and ships with the installed package. Once you pip install truffile, the same runtime is importable from app code running on your device. There are two other entry points that import the same names:
  • from truffile.sdk import ... — a curated re-export module with nice grouping. Use this if you prefer one obvious “public API” import.
  • from truffile import ForegroundApp, BackgroundWorkerApp, ToolSpec, ok, err, OAuth, AppHarness — the most common names are also re-exported at the top level.
All three forms resolve to the same objects. Pick whichever reads best for you. The examples in this guide use truffile.app_runtime because it is the clearest app-authoring import surface.

Scaffold a new app

The fastest way to start:
Flags:
  • truffile create <name> — set the name, prompt for base path
  • truffile create <name> --path <dir> — set name and base path
  • truffile create — fully interactive
The generated my_app_foreground.py and my_app_background.py are stubs using the real SDK classes. Delete whichever you don’t need — the app type is inferred from which foreground / background sections you keep in truffile.yaml.

Let an agent build the app for you

If you’re working in the truffile repo with a coding agent — Claude Code, Codex, or any other agent that can read skill files — there’s a built-in skill it can follow to build a Truffle app end-to-end: truffle-app-creator (at truffile/skills/truffle-app-creator/SKILL.md). It’s the fastest path for things like:
  • “Create a Truffle app that talks to <service>”
  • “Port this MCP server to Truffle”
  • “Build an integration with <API> and run it in the background”
The skill handles architecture decisions (foreground/background/hybrid, auth type, base image), uses truffile create to scaffold, implements the client/auth/tools, writes tests, and runs truffile validate + truffile deploy for you. Just describe the service you want to connect and it takes over from there.

truffile.yaml structure

Every app needs a truffile.yaml. Minimum viable config:

Supported step types

Steps run during installation on the device, in order. The manifest supports: See the Install steps reference for every option on each type — field shapes, validators, exit code semantics, and multi-field examples.
vnc / browser setup steps are not supported through truffile. truffile validate rejects them with an explanation and tells users to install those apps through Symphony Settings.

Auth patterns

Pick the smallest auth surface that matches the upstream service: For text auth, add a validator that calls python ./foreground.py --verify or python ./background.py --verify. For OAuth, write a tiny auth helper around OAuth or RemoteMcpOAuth, store the token file path in an env var, and verify it in a follow-up bash step. If an update reaches an auth step that cannot be refreshed non-interactively, fail clearly and tell the user to reauthenticate from Settings.

Build and deploy flow

  • validate checks the truffile.yaml structure, confirms referenced files exist, and parses all Python files for syntax errors.
  • deploy --dry-run builds the deploy plan without changing anything on the device, so you can see what files will be uploaded, what bash steps will run, and how the process config will look.
  • deploy opens a build session on the device, uploads files, runs your steps in order, and registers the app.
Add --interactive to deploy to open a shell inside the app’s container when the build steps finish — useful for installing extra packages or debugging before finalizing. After deployment, use an agent-safe one-shot request as a routing smoke test:
Inspect tool_calls in the JSON result. This tests normal agent discovery and tool routing only. Convo has no per-thread app allowlist, so the CLI cannot attach the newly deployed app or guarantee that this request uses it. Use truffile infer --mcp <url> before deployment when you need deterministic local selection of the app’s MCP server.

Runtime stability pattern

Whatever network clients your app opens — HTTP sessions, database connections, MCP subprocesses — close them on shutdown:
Leaving outbound connections open at process exit is the most common source of flaky redeploys and container runtime crashes. Every example app in the repo does this.

Next steps

Build a Foreground App

Use ForegroundApp to expose MCP tools the agent can call on demand.

Build a Background App

Use BackgroundWorkerApp to run on a schedule and submit context to the proactive agent.