When an agent deploys an app, it creates a manifest, a description of everything the app needs to run. This is what you see during the approval flow, and understanding it helps you make good decisions about what to approve.
Reading a manifest
Here's an annotated example of a service app manifest:
# Identity
handle: sales-dashboard # URL-safe identifier; source lives at apps/sales-dashboard/
# and is served at /apps/sales-dashboard/. Immutable once deployed.
# 2–32 chars, must start with a lowercase letter, then a-z, 0-9, -, _.
name: Sales Dashboard # Human-readable display name
description: Interactive dashboard showing quarterly sales data
icon: chart-bar # Optional icon hint shown in the apps UI
# Mode
kind: service # 'service' (running process, default) or 'static' (files only)
# How to run it
command: node server.js # Start command, run from apps/{handle}/. Must listen on $PORT.
# static_dir: dist/ # For kind: static — directory to serve, relative to apps/{handle}/
# Reverse proxy
expose: true # Default true. Set false for background workers (no URL).
# Sandbox policy
sandbox_policy:
network_access: true # Master switch for outbound network
network_destinations: # Allowlist of "host:port" strings (used when network_access is true)
- "api.example.com:443"
read_paths: # Extra filesystem reads. Absolute, user://, or agent:// paths only.
- "user://alice/reports"
write_paths: # Extra filesystem writes
- "/tmp/cache"
bind_ports: # TCP ports the app may listen on (in addition to $PORT)
- 9000
denied_paths: # Deny rules layered on top of allows
- "/etc"
blocked_networks: # Block these destinations even if network_access is true
- "169.254.169.254:80"
# Resource limits
resources:
memory_mb: 256 # Max memory
cpu_shares: 512 # CPU weight
max_pids: 50 # Max processes
# Credentials
credentials: # Vault items injected as environment variables
- query: OpenAI API key
reason: Used for generating chart descriptions
env_var_prefix: OPENAI # Creates OPENAI_USERNAME, OPENAI_PASSWORD, etc.
# Health checks (services only)
health_check:
path: / # Default '/'
interval_secs: 10 # Default 10
timeout_secs: 2 # Default 2
initial_delay_secs: 5 # Default 5
failure_threshold: 3 # Default 3
# Lifecycle
restart_policy: on_failure # 'on_failure' (default), 'always', or 'never'
hibernate: true # Default true. Set false for always-on services.What to look for when approving
When reviewing a manifest, pay attention to:
command. What program will run? Does it look reasonable for what you asked?sandbox_policy.network_destinations. Does the app need to reach external services? If you asked for a simple dashboard, it probably shouldn't need network access.credentials. Is the app requesting API keys or passwords? Make sure the reason is legitimate.sandbox_policy.read_paths/write_paths. What files can the app access? It shouldn't need access beyond its own directory unless there's a specific reason.
These five fields — command, kind, expose, sandbox_policy, credentials — are the ones that trigger a fresh approval prompt when they change on an already-deployed app. Touching code, names, or icons restarts the app silently.
Common manifest patterns
Simple static site (no network, no credentials)
A data visualization page built from a CSV you uploaded:
kind: static, nosandbox_policy, nocredentials- This is the safest kind of app. It's just serving files.
API-connected service
A dashboard that fetches live data from an external API:
kind: service,sandbox_policy.network_destinations: ["api.example.com:443"],credentials: [API key]- Review that the API destination and credentials match what you expect.
Internal tool
A service that processes workspace files:
kind: service,sandbox_policy.network_access: false,sandbox_policy.read_paths: ["user://<handle>/..."]- No external access, just reading your files. Relatively safe.
Managing deployed apps
Stopping an app
Stops the running process but keeps the app configuration. You can restart it later.
Restarting an app
Stops and immediately restarts. Useful to pick up environment changes or clear a bad state.
Destroying an app
Permanently removes the app. The source code remains in the agent's workspace, but the app configuration and process are deleted. To run it again, the agent would need to redeploy.
Server-level settings
These settings control app behavior across your entire instance:
| Setting | Default | Description |
|---|---|---|
FRONA_APP_PORT_RANGE_START | 4000 | First port available for apps |
FRONA_APP_PORT_RANGE_END | 4100 | Last port available for apps |
FRONA_APP_HEALTH_CHECK_TIMEOUT_SECS | 30 | Timeout for health checks |
FRONA_APP_MAX_RESTART_ATTEMPTS | 2 | How many times to restart a crashed app |
FRONA_APP_HIBERNATE_AFTER_SECS | 259200 | Inactivity before hibernation (default: 3 days) |
Tips
- Simpler manifests are safer. A static site with no network access is always safer than a service with external connections.
- Don't over-provision resources. Most simple apps work fine with default memory and CPU settings.
- Check credentials carefully. If an app requests credentials, make sure you understand why and that the
env_var_prefixmakes sense.
Next steps
- Building & Deploying Apps. The full app deployment workflow.
- Managing Secrets & API Keys. How credential requests work.
- Sandbox. How sandboxing protects your system.