Feature flags
Turn a Beeuni surface on for one project, and read what every flag gates.
A feature flag turns one Beeuni surface on for one project. Any surface can ship behind a flag — experimental, beta, or fully stable. “Experimental” is a stability badge on a flag, not the name of the system.
Flags are per project. Turning a flag on in one project changes nothing in another project, and nothing for other accounts.
Turn a flag on
- Open Settings → Feature flags. The tab lists every flag the platform supports.
- Read the row: the flag name, its stability badge, one sentence of
description, and its origin —
Default on,Default off, orOverridden for this project. - Use the switch. The change applies to the current project immediately.
You need the project’s project.settings.write permission. The route answers
403 for any other caller.
From the CLI
The same switches are available to scripts and agents through beeuni projects features:
beeuni projects features # every flag: key, state, origin
beeuni projects features enable reminders
beeuni projects features disable reminders
beeuni projects features reset reminders # drop the override; follow the platform default
beeuni projects features --json # the full catalog as JSON
Add --project <id> to act on a project other than the linked/default one. A
flag the platform marks unavailable stays off whatever the project override
says; the CLI prints that as n/a / unavailable.
Stability badges
The badge describes the contract, not the switch. A stable flag is still an
opt-in: apps is stable and still off by default.
| Badge | What it means |
|---|---|
| Experimental | The surface and its contract can still change. |
| Beta | The surface works and the shape is settling. |
| Stable | The contract holds. The flag stays an opt-in. |
How a flag is enforced
Every flag declares one enforcement mode.
| Mode | What the server does when the flag is off |
|---|---|
routes |
The HTTP surface rejects the request with 403. |
behavioral |
The behavior does not occur — no connector materializes, no env injects, no agent registers. |
ui-only |
The server deliberately does not enforce. The flag hides client surface only. |
A routes rejection is identical everywhere:
{
"error": "Apps is not enabled for this project. Contact Beeuni to enable it.",
"code": "feature_disabled",
"feature": "apps"
}
The error string names the flag list, not a specific tab. The list is the
Experimental tab of Settings.
Branch on code, never on the message text. The SDK exports
isFeatureDisabledError(error) and featureDisabledKey(error) for exactly
this.
Every flag
Registry order — the same order Settings → Feature flags shows.
Apps are enabled per project by Beeuni. Contact Beeuni to request access. When enabled, Settings shows them as Managed by Beeuni.
| Key | Name | Stability | Default |
|---|---|---|---|
marketplace |
Marketplace | Beta | On |
connectors_api_discover |
Connectors API Discover | Experimental | Off |
agentmail_email |
AgentMail Email | Experimental | Off |
llm_gateway |
LLM Gateway | Experimental | On |
meta_agent |
Meta Agent | Experimental | Off |
apps |
Apps | Stable | Off |
monitors |
Monitors | Experimental | Off |
reminders |
Reminders | Beta | Off |
warm_sessions |
Warm Sessions | Beta | On |
secrets_egress |
Network-Enforced Secrets | Experimental | On |
pi_harness |
Pi Harness | Experimental | Off |
What each flag gates
marketplace— browse and install skills from community and vendor registries.connectors_api_discover— browse direct API, MCP, GraphQL, CLI, and Postman surfaces beside managed OAuth apps. See Connectors.agentmail_email— assign AgentMail inbox connections so inbound email starts and continues sessions.llm_gateway— route the project through the managed Beeuni LLM gateway. See Models.meta_agent— add a platform-owned coordinator agent that spawns and manages specialized sessions.apps— deploy static sites, bundles, Dockerfiles, and OCI images to stable serverless URLs. See Apps.monitors— run 24/7 watchers from your repo that fire trigger events into sessions. See Triggers.reminders— scheduled check-ins that re-prompt one session, once or on repeat. Off, the reminder routes answerfeature_disabledand existing reminders do not fire. See Reminders.warm_sessions— keep one sandbox booted while a project is open, so a new session starts without a cold boot.secrets_egress— offer network enforcement for a secret: the sandbox holds a handle, and Beeuni substitutes the real value only on requests to approved hosts. See Secrets.pi_harness— run this project’s sessions on the pi agent harness inside the ordinary session sandbox (BEEUNI_HARNESS=pi). On: every new or restarted session boots pi, whatever the manifest says. Off: the manifest decides —runtime: pistill boots pi, anything else boots default runtime. pi calls models only through the LLM gateway: withllm_gatewayoff, every session boots default runtime, whatever this flag or the manifest says. Same repo layout, agents and skills either way; a running session keeps its harness until it is restarted or resumed. Subagents work on pi: the agent delegates with thetasktool togeneral,explore(read-only), or any project agent withmode: subagentin its.md, and the transcript shows each subagent’s steps in place. pi sessions also load pi.dev packages: seeharnesses:. pi does not serve every session feature default runtime does: see the matrix in Harnesses.
Graduated flags
A graduated feature is on for every project and has no switch.
- Agents as principals is standard behavior with no switch. An agent session acts as the agent itself — its Beeuni permissions within its ceiling role, whoever runs it. See Agent permissions.
- Review Center graduated out of the flag system. The Review page, the
sidebar Review row, and the command-palette row show for every project; the
project.review.readandproject.review.actpermissions still apply.review_centeris no longer a flag key:PATCH /v1/projects/:id/featuresanswers400Unknown feature flag, andbeeuni projects features enable review_centerprints that error and exits1. A stored override from before graduation has no effect. - Computers graduated out of the flag system. Every member can connect
their own computer from the project sidebar; the platform’s
TUNNEL_ENABLEDsetting is the only gate.agent_tunnelis no longer a flag key:PATCH /v1/projects/:id/featuresanswers400Unknown feature flag. See Computers. - Microsoft Teams graduated out of the flag system. Every project can
connect Teams from Connectors → Channels; a tenant admin still consents
once, or the project brings its own bot.
teamsis no longer a flag key:PATCH /v1/projects/:id/featuresanswers400Unknown feature flag. A stored override from before graduation has no effect. See Microsoft Teams.
Side effects of a toggle
Some flags converge platform state after the write commits.
| Flag | Effect after the toggle |
|---|---|
agentmail_email |
Beeuni re-runs channel-connector materialization, so the connector appears or disappears with the flag. |
llm_gateway |
Beeuni propagates the new provider mode to active sandboxes. |
Effects are convergence work, not part of the toggle’s success. The API response does not wait for them. Each effect is retried once, and the reconcilers behind it are idempotent and re-run on their periodic sweeps.
Read and set a flag from code
Read the effective per-project state through the project detail, or through the React hook:
import { useFeatureFlag } from '@beeuni/sdk/react';
function AppsNavItem({ projectId }: { projectId: string }) {
const apps = useFeatureFlag(projectId, 'apps');
if (!apps.enabled) return null;
return <Link href={`/projects/${projectId}/apps`}>Apps</Link>;
}
enabled is true only when the server said exactly true. A missing project
id, an in-flight query, and an error all resolve to false. Gate fail-closed.
Set the project override with the client:
const p = beeuni.project(projectId);
await p.updateFeatureFlag('apps', true); // turn it on for this project
await p.updateFeatureFlag('apps', null); // clear the override, inherit the default
updateFeatureFlag calls PATCH /v1/projects/:id/features. feature is one
of FEATURE_FLAG_KEYS, exported from @beeuni/sdk and typed as
FeatureFlagKey. See SDK reference.
Handle a disabled feature by code, not by message:
import { featureDisabledKey, isFeatureDisabledError } from '@beeuni/sdk';
try {
await beeuni.project(projectId).apps.list();
} catch (error) {
if (isFeatureDisabledError(error)) {
console.log(`${featureDisabledKey(error)} is off for this project`);
}
}