Skip to main content
The config dict you hand to bindufy() is the whole settings surface. Four keys are required (three at the top level plus deployment.expose). The rest have defaults that work for localhost, and env-var overrides for when you ship.

The required keys

The top-level validator checks three fields. A fourth, deployment.expose, is required by the deployment builder (bindufy.py:332) once deployment is present.
Miss author, name, or deployment.url and the config validator raises ConfigError: '<field>' is a required field in the agent configuration. with an example config attached. Miss deployment.expose (when a deployment block is present) and the deployment builder raises ValueError: Missing required config field(s): deployment.expose — different error class, different message format.

The keys you’ll actually touch

Everything below has a sensible default (taken from ConfigValidator.DEFAULTS). You override when you care.

Storage and scheduler — set these via env

Putting database credentials in a Python dict is how secrets end up in git. The env-enricher fills these in for you when storage / scheduler aren’t already in the config dict.
Bindu refuses to start if STORAGE_TYPE=postgres but DATABASE_URL is unset (same for SCHEDULER_TYPE=redis / REDIS_URL) — no silent fallback to memory. Local dev: leave both unset, you get in-memory. Production: set both, you get persistence and distributed task queues. Same bindufy(config, handler) either way. Deeper guides: Storage, Scheduler.

Auth, payments, and the rest

These are off by default. Turn them on when you need them — each one has its own page that goes deeper than this reference should. The pattern is consistent: feature lives in config if it’s about agent identity or behavior, in env vars if it’s about infrastructure or secrets.

The “okay show me everything” example

Most production agents look something like this:
Everything else — storage, scheduler, Hydra URLs, OLTP endpoint, x402 facilitator — comes from env vars at deploy time. The dict stays small and your secrets stay out of git. You did not write the validator; the validator wrote you a useful error message instead.

What you can’t put in here

config is for static settings. If you’re trying to:
  • pass dynamic state per request → use the handler’s messages arg
  • share data between handler invocations → use Storage, not module-level globals
  • override behavior at runtime → you probably want a skill, not a config key
If you find yourself wanting a config key that isn’t here, open an issue — half the time it’s already in bindu/penguin/config_validator.py under a name we forgot to document. The other half it’s a real feature gap and we want to know.