Skip to content

Flags Management

Most customers create and configure flags via the Console UI. The management API is for infrastructure-as-code, CI/CD pipelines, setup scripts, and automated testing. Management operations are stateless HTTP calls — no WebSocket or start() needed.

Management lives at client.manage.flags.* on the runtime client. For setup scripts and admin tooling, construct a standalone SmplManagementClient directly — same surface, no WebSocket or metrics overhead.

Create a Boolean Flag

The flag is created locally — nothing hits the server until save() is called.

python
import asyncio
from smplkit import AsyncSmplManagementClient

async with AsyncSmplManagementClient() as manage:
    checkout = manage.flags.new_boolean_flag(
        "checkout-v2",
        default=False,
        description="Controls rollout of the new checkout experience.",
    )
    await checkout.save()

Create a String Flag

String flags can be constrained (closed set of allowed values) or unconstrained. The values parameter defines the allowed set — the Console UI shows a dropdown for value selection.

python
from smplkit import FlagValue

banner = manage.flags.new_string_flag(
    "banner-color",
    default="red",
    name="Banner Color",
    description="Controls the banner color shown to users.",
    values=[
        FlagValue(name="Red", value="red"),
        FlagValue(name="Green", value="green"),
        FlagValue(name="Blue", value="blue"),
    ],
)
await banner.save()

Create a Number Flag

Omit values for an unconstrained number flag — any number is valid. Useful for tunables like thresholds, retry counts, and timeouts.

python
retries = manage.flags.new_number_flag(
    "max-retries",
    default=3,
    description="Maximum number of API retries before failing.",
)
await retries.save()

Create a JSON Flag

JSON flags serve complex configuration objects. Like string flags, they can be constrained to a set of predefined values.

python
from smplkit import FlagValue

theme = manage.flags.new_json_flag(
    "ui-theme",
    default={"mode": "light", "accent": "#0066cc"},
    description="Controls the UI theme configuration.",
    values=[
        FlagValue(name="Light", value={"mode": "light", "accent": "#0066cc"}),
        FlagValue(name="Dark", value={"mode": "dark", "accent": "#66ccff"}),
        FlagValue(name="High Contrast",
                  value={"mode": "dark", "accent": "#ffffff"}),
    ],
)
await theme.save()

Targeting Rules

Rules define conditions under which a flag serves a specific value. Build rules with the fluent Rule builder. The environment is required — it scopes the rule to a single environment. Multiple .when() calls within a rule are AND-ed together.

Supported operators: ==, !=, >, <, >=, <=, in, contains. Python and TypeScript also expose them as Op.EQ, Op.NEQ, etc.

Single-condition rule

python
from smplkit import Op, Rule

checkout.add_rule(
    Rule("Enable for enterprise users", environment="staging")
    .when("user.plan", Op.EQ, "enterprise")
    .serve(True)
)
await checkout.save()

Multi-condition rule

python
checkout.add_rule(
    Rule("Enable for enterprise users in US region", environment="staging")
    .when("user.plan", Op.EQ, "enterprise")
    .when("account.region", Op.EQ, "us")
    .serve(True)
)
await checkout.save()

Per-Environment Defaults and Kill Switch

Each environment has its own default value (falls back to the flag default if unset) and an enabled flag (the kill switch). When enabled is false, rules are skipped and the per-environment default is served.

python
# Per-environment default — wins over the base flag default in this env.
checkout.set_default(False, environment="production")

# Kill switch — bypass all targeting rules in production.
checkout.disable_rules(environment="production")
checkout.enable_rules(environment="staging")

# Revert overrides:
checkout.clear_default(environment="production")
checkout.clear_rules(environment="staging")     # remove every rule on staging

await checkout.save()

List and Get Flags

python
flags = await manage.flags.list()
for f in flags:
    envs = list(f.environments.keys()) if f.environments else []
    print(f"  {f.id} ({f.type}) — default={f.default}, environments={envs}")

fetched = await manage.flags.get("checkout-v2")
print(f"id={fetched.id}, type={fetched.type}, default={fetched.default}")

Update a Flag

Fetch a flag, mutate, save. Constrained-flag values can be added with add_value/addValue/AddValue and removed wholesale with clear_values/clearValues/ClearValues (which makes the flag unconstrained).

python
banner.add_value("Purple", "purple")
banner.default = "blue"
banner.description = "Controls the banner color — updated"
banner.add_rule(
    Rule("Purple for enterprise users", environment="production")
    .when("user.plan", Op.EQ, "enterprise")
    .serve("purple")
)
await banner.save()

Delete a Flag

python
await manage.flags.delete("checkout-v2")
# or:  await checkout.delete()

Sync Client (Python)

For synchronous applications, use SmplManagementClient instead of AsyncSmplManagementClient:

python
from smplkit import SmplManagementClient, Op, Rule

with SmplManagementClient() as manage:
    flag = manage.flags.new_boolean_flag("my-flag", default=False)
    flag.save()

    flag = manage.flags.get("my-flag")
    flag.add_rule(
        Rule("...", environment="staging")
        .when("user.plan", Op.EQ, "enterprise")
        .serve(True)
    )
    flag.save()

    manage.flags.delete("my-flag")

From a runtime client

Inside a service that already holds a SmplClient, use client.manage.flags.* to avoid juggling two clients:

python
from smplkit import SmplClient, Rule, Op

with SmplClient(environment="production", service="my-service") as client:
    banner = client.manage.flags.get("banner-color")
    banner.add_rule(
        Rule("Red for small companies", environment="staging")
        .when("account.employee_count", Op.LT, 50)
        .serve("red")
    )
    banner.save()

The same pattern applies in every SDK: client.manage.flags.* (Python/TS/C#), client.Manage().Flags() (Go), client.manage().flags (Java).

Next Steps