Skip to main content

fireweave (Python SDK)

Fireweave release-engineering SDK for Python — control points and target registration, the two v1 capabilities (spec/control-points.md "Scope of v1").

  • Zero runtime dependencies.
  • The core SDK reads no environment variables — every option is an explicit argument to init_fireweave (spec/modes.md). The opt-in start profile, fireweave.start, is the one documented exception (ADR-0012).
  • No vendor SDK, key, or hostname in your process. Applications hold a Fireweave project key and talk to fw-server; which backend fw-server forwards to is fw-server's concern.

Quick start (one line: the start profile)

Most apps need only this (ADR-0012). One small module and one call:

# src/fireweave_setup/control_points.py: every control point the app reads, with its local value
from fireweave.start import define_control_points

control_points = define_control_points({
    "new-checkout": {"local": True, "description": "One-page checkout"},  # served only in local mode
})
# the process entrypoint, FIRST thing: main.py, wsgi.py + asgi.py, create_app(), the Celery app module
from fireweave.start import start
from fireweave_setup.control_points import control_points

start(control_points=control_points)
# any call site
from fireweave import EvaluationContext
from fireweave.start import fw

# @fireweave-controlpoint new-checkout
if fw.control_points.get_boolean_value("new-checkout", False, EvaluationContext(user_id)):
    ...
fw.identify(user_id, {"plan": user.plan})                                   # at sign-in
fw.control_points.get_boolean_value("nightly-reindex", False, EvaluationContext(fw.instance_key()))  # server as subject

Deployed environments set one variable, FIREWEAVE_KEY (the project key, project-api-key_…). Local development needs nothing when FIREWEAVE_ENV (or APP_ENV) is development, dev, local or test.

fw.control_points has exactly the core's nine methods, with the same names and arguments; contexts are EvaluationContext as everywhere else. Reads are synchronous (one blocking HTTP call each in remote mode); in an async def handler use await asyncio.to_thread(lambda: fw.control_points.get_boolean_value("new-checkout", False, ctx)). Never pass an unguarded str(user.id): Django's AnonymousUser.id is None, and "None" would be one targeting key shared by every anonymous visitor.

Options and overrides

Every value resolves as: start() keyword option, then env var, then legacy name (warns once), then default. Empty and whitespace-only values count as unset.

Option Env var Default What it does
control_points — {} Local values per control point. Ignored in remote mode.
mode — inferred 'remote' or 'local'. Overrides inference. 'remote' without a key is a start error; 'local' ignores a key, with one warning.
environment FIREWEAVE_ENV, APP_ENV — Environment name used for inference when there is no key and no mode. Pass your own, e.g. environment=settings.DEPLOY_STAGE. ENVIRONMENT, ENV, NODE_ENV and the retired FW_ENV are not read.
url FIREWEAVE_URL (legacy FW_API_URL, FW_ATTEST_URL) from the installed version A pre-release or dev release calls staging-app-server.fireweave.ai; any other calls app-server.fireweave.ai. Staging builds are X.Y.ZrcN on PyPI: install one with pip install fireweave==X.Y.ZrcN (no extra index; pip skips pre-releases unless pinned). Set it for a self-hosted or local fw-server: https is required except on localhost, and the host allowlist follows it.
key FIREWEAVE_KEY (legacy FW_PROJECT_API_KEY) — Project key. Pass it to read from your own secret store. Browser keys (fw_public_…), analytics vendor keys and org or CLI tokens are rejected at start.
instance_id FIREWEAVE_INSTANCE_ID inst_ + hash of the host name Value of fw.instance_key(). Nothing is written to disk.
env — os.environ Read values from this mapping instead of the environment (tests).
log — the fireweave.start logger A callable taking one line, or a logging.Logger. Where [fireweave] lines go.

fireweave.start.SDK_VERSION and SDK_CHANNEL show which version and channel are installed.

Mode rule. mode wins. Otherwise: a key means remote. No key and a development environment name means local. Anything else (including no environment name at all) raises ConfigurationError at start(), naming FIREWEAVE_KEY and where the environment name was looked for, so a deploy that forgot its key fails instead of silently serving defaults.

One per process. start() is idempotent: a second call with the same configuration does nothing, a different one raises ConfigurationError. It does no network I/O and starts no thread, so it is ready when it returns. Call it in every process entrypoint; a forked worker (gunicorn --preload, Celery prefork) rebuilds its client on its own. A read before any start() starts FireWeave immediately from the environment alone (one warning); the first explicit start() afterwards replaces that once, with a warning, and shuts the provisional client down (reads in flight move to the new one). Processes that never run your entrypoint (manage.py, spawned children) get the environment-only start, so prefer FIREWEAVE_* variables to options for anything every process needs.

Reads never raise. If start fails, reads return your default (evaluate and the *_details forms return an ERROR decision with the Configuration error) and fw.identify() returns ok=False. In local mode, reading a key that is not in your control points returns the default and warns once, naming the file that declared them.

Debugging. fw.status() reports what start decided: state, started_by, mode and mode_source, channel, sdk_version, host, endpoint_source, key_source, environment, flag_count, error and last_error_kind. It never includes the key. When fw-server refuses the key (401/403), rate-limits it (429) or cannot be reached (network error, timeout, 5xx or a redirect, which is never followed), reads serve their defaults, so a revoked key would otherwise look like a rollout at 0%. Each of those kinds logs one line per process through your log sink (default: the fireweave.start logger), naming the key's source (FIREWEAVE_KEY, start(key=...)) or the endpoint's, and the host, never the key; last_error_kind keeps the latest kind (Authentication, Authorization, RateLimited, Network, Timeout, BackendUnavailable). fw.client() is the core FireweaveClient for anything the facade does not cover (do not cache it: the first explicit start() after a read-triggered one shuts the provisional client down); fw.shutdown() flushes and closes, and a later start() begins fresh. Tests call fireweave.start.reset_for_tests() between cases.

Quick start (production path)

from fireweave import RegisterTargetOptions, init_fireweave, EvaluationContext

# mode is required and never inferred (spec/modes.md); api_key/api_url are
# explicit options — the SDK reads no environment variables.
client = init_fireweave(
    mode="remote",
    api_key="project-api-key_...",
    api_url="https://app-server.fireweave.ai",
)

# Once per login: the durable facts your targeting rules match on.
client.register_target(
    "user_42", RegisterTargetOptions(kind="user", properties={"plan": "pro"})
)

# Per request.
enabled = client.control_points.get_boolean_value(
    "new-checkout", False, EvaluationContext("user_42")
)

client.shutdown()

Quick start (offline, in-memory)

from fireweave import FireweaveClient, FireweaveRuntime, InMemoryAdapter

adapter = InMemoryAdapter({
    "new-checkout": {"enabled": True, "variant": "on", "value": True},
})
runtime = FireweaveRuntime(adapter)
runtime.initialize()
client = FireweaveClient(runtime)

assert client.control_points.get_boolean_value("new-checkout", False) is True
client.shutdown()

Quick start (local dev — no network, no credentials)

from fireweave import init_fireweave

client = init_fireweave(mode="local", local={"control_points": {"new-checkout": True}})
client.control_points.get_boolean_value("new-checkout", False)  # -> True
client.register_target("user_42")  # recorded in-process + traced; nothing sent
client.shutdown()

The nine methods

get_boolean_value / get_string_value / get_number_value / get_object_value, their *_details counterparts (return the whole Decision — reason, error_kind, control_point_metadata, ... — instead of just the value), and the general-form evaluate. All nine live under client.control_points; the client.flags alias was removed in 3.0.0 (ADR-0013).

get_integer_value is a deprecated alias of get_number_value — spec fixes the method as number, not integer (Decision.value is jsonValue). It still works and delegates straight through; it logs one DeprecationWarning per process the first time it's called.

Module layout

Module Responsibility
domain/ Pure types + validation: errors.py, types.py, context.py, decision.py, target.py, validation.py. No I/O, no imports from application//infrastructure/.
application/runtime.py Lifecycle state machine, context layering, the evaluation pipeline. Evaluation never raises.
application/client.py FireweaveClient — control_points, register_target, invoke_capability (degrades; v1 has no supported capabilities).
application/mode.py init_fireweave — the single entry point and sanctioned composition root (the only file allowed to import concrete adapters).
application/ports.py The BackendAdapter boundary.
infrastructure/adapters/remote.py FireweaveRemoteAdapter — the production backend (POST /v1/control-points/evaluate, POST /v1/targets/register).
infrastructure/adapters/local.py FireweaveLocalAdapter — the dev substrate: seeded boolean overrides, no network. register_target records in-process and traces the call.
infrastructure/adapters/memory.py Deterministic fixture-driven adapter for tests.
infrastructure/hosts.py SSRF allowlist (on by default; https required off-loopback).
start/ The opt-in start profile (from fireweave.start import start, fw, define_control_points). Built on the public fireweave API only; start/_env.py is the one file that reads the environment or the host name. The core never imports it.

Development

python -m venv .venv && .venv/bin/pip install -e '.[dev]'
# or: uv sync
.venv/bin/pytest    # unit tests

conformance/surface/control-points.surface.json is the parity gate this package satisfies.

License

MIT.

Metadata

Release files for fireweave 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fireweave 3.0.0
File Size Uploaded Provenance Actions
fireweave-3.0.0.tar.gz 93.6 kB Without provenance Details for fireweave-3.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fireweave 3.0.0
File Interpreter ABI Platform Actions
fireweave-3.0.0-py3-none-any.whl Python 3 none any Details for fireweave-3.0.0-py3-none-any.whl

Total release size: 158.6 kB

Release files / fireweave-3.0.0.tar.gz

Download URL fireweave-3.0.0.tar.gz
Size 93.6 kB
Tags Source
SHA-256 checksum
How to use checksums
1ac2dea4838cc565c5366f3de26f1df71d3f105423b25539669adb2d678847d6
BLAKE2b-256 checksum
How to use checksums
f94c26495b9d8422afe5c991b1026a13b84adc8444179adedeacd1fe3de61912
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / fireweave-3.0.0-py3-none-any.whl

Download URL fireweave-3.0.0-py3-none-any.whl
Size 65.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
610d336fbf71bfc79c9c4dee4f3139f0b0c8a3fb61d8828c954e989e34585f6d
BLAKE2b-256 checksum
How to use checksums
8cb80d758a26611dbec20889592d8ec0253cc20c22ec4dfd89e8fe16261e363c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for fireweave 3.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page