Skip to main content
Most agents have values that change more often than the code: a tone, a follow-up delay, a list of topics that go to a human, the units a single agent serves. Agent Config lets you declare those values once, in code, with types and defaults, and gives the portal a form to edit them per environment. Saving takes effect on the next execution. No deploy, no redeploy.
Configuration tab with a list of hotels on the left and the selected hotel's form on the right

The Configuration tab of an agent that serves several hotels

Agent Config is rolled out per workspace. If an agent declares a manifest but you don’t see the Configuration tab, ask Runflow to enable it for your workspace. The code side works either way: the defaults you declare are always delivered to the agent.

How it works

You describe the config with a Zod schema in manifest/index.ts. When you deploy, the CLI turns it into agent.manifest.json, the platform builds a form from it, and every execution receives the resolved values. Inside the agent you read them with config(). Values come from three layers. The higher layer wins, field by field: A field nobody touched shows its default in the portal. A field changed in the portal is marked as changed and can be restored to the default with one click.

Quick start

1

Declare the schema

Create manifest/index.ts. The default export is defineManifest({ config }).
manifest/index.ts
2

Read it in the agent

Import the manifest once in your entry file, then call config() wherever you need the values.
main.ts
Keep the import ... from './manifest'. It registers the schema, so config() validates the values and applies Zod transforms. Without it you still get the values, but untyped and unvalidated.
3

Deploy

The CLI generates agent.manifest.json from manifest/ and ships it with the code. If the schema or a JSON file in manifest/ is invalid, the deploy stops before uploading anything.
4

Edit in the portal

Open the agent, go to Configuration, change a value and click Save in staging. The next staging execution already sees it. When it looks right, click Promote to production.

From schema to form

The portal renders each Zod type with a matching control. You don’t write any UI. Everything you put in .meta({...}) shapes how the field is shown:
Conditional field

Collections: one agent, many units

When one agent serves several stores, hotels, clinics or brands, declare a collection with z.record. Each item gets its own form, and the team adds a unit in the portal without touching code.
manifest/index.ts
In the portal the collection becomes a searchable list on the left. Each item opens as one continuous form, with its nested objects as sub-sections you can jump to. New items are validated before the save, and the save button says what is missing.
New hotel being created with validation errors on required fields

A new item with required fields still empty: the save is blocked and the list marks the item

Some details worth knowing:
  • The key is the item id. The portal suggests it from the name (Hotel Copacabana becomes hotel-copacabana). Use it in code and in logs. Keys can’t contain ..
  • Defaults apply inside each item. A field with .default() in the item schema is filled for every item, including items added later in the portal.
  • Duplicate copies every field, including ids such as channel or branch codes. Change those before saving.
  • Items can be declared in the repository too. An item in manifest/staging.json shows up in the portal, where the team can adjust its fields. It can’t be removed from the portal, since the repository would bring it back on the next deploy.
  • Always add .default({}) to the collection, so the agent gets {} and not undefined before the first item exists.
See One agent for many units for a complete example routed by WhatsApp number.

Environments, promotion and history

Config follows the same environments as the rest of the platform:
  • Staging is where you edit. Save in staging creates a new version and it applies on the next staging execution.
  • Production is read-only in the tab. It changes only through Promote to production, which shows exactly which fields change before you confirm. Promoting requires an admin of the workspace.
  • History lists every version with author, date and message, the diff against the previous one, and Restore, which creates a new version with the old values. Nothing is overwritten.
Promote the code before the config that depends on it. If production still runs a version of the agent without a field, the promote dialog explains it and stays blocked until the code is promoted.
Defaults that differ per environment, such as a sandbox URL in staging, go in the repository files. They must match the schema, and the deploy fails if they don’t.
manifest/staging.json

Reading request metadata

Agents that pick a unit per request need something from the incoming request, like a store id or the number that received the message. readMetadata(input) merges the metadata of the execution input with the metadata sent in the request body by HTTP triggers, so the same code works for the portal tester, the CLI and real traffic.
The Conversation Hub sends the WhatsApp number as phoneNumberId at the top of the request body, not inside metadata. Read it from input.request?.body?.phoneNumberId; the multi-unit guide shows how to support both.
To test with realistic metadata in the portal, declare a playground. The fields become a form in the agent tester and each fixture becomes a one-click scenario:
manifest/index.ts
Fixtures can also live in manifest/fixtures/*.json, as an array of { name, description?, metadata }. Use fictional data: the CLI warns when a fixture looks like a real e-mail or phone number.

CLI

Inspecting what the agent received

configInfo() tells you which version an execution ran with. Log it next to your business events and you can tell later which settings produced a given answer.
If stale: true shows up, the execution ran on a version of the code whose manifest differs from the one the config was saved for. That happens briefly right after a deploy that changed the schema; saving once in the portal clears it.

Limits and good practices

  • The resolved config of one environment can be up to 192 KB. That fits dozens of units with long prompt instructions. If you need more, the data probably belongs in a KV store or a knowledge base.
  • Config is not a secret store. Anyone who can open the agent can read it. Keep API keys and passwords in Credentials and reach them through connectors.
  • Validate in the schema, not in the agent. A .min(1) or .max(168) in the schema blocks a bad value in the portal before it reaches production.
  • Removing or renaming a field is a breaking change. Values saved for a field that no longer exists are ignored and listed as invalid in the tab, so rename in two steps: add the new field, migrate, then remove the old one.
  • When the values don’t match the schema (for example, after a type change), config() logs a warning in the execution output and uses the values over the code defaults. Check the execution logs after changing a field’s type.

FAQ

Do I need to redeploy after saving in the portal?

No. The next execution reads the new version.

Who can change the config?

Members of the workspace can save in staging. Promoting to production and restoring a production version require an admin.

What happens to executions already running when I save?

They finish with the values they started with. Only new executions see the new version.

Can I use a JSON Schema instead of Zod?

Yes. defineManifest({ config }) also accepts a plain JSON Schema object. You lose type inference and Zod transforms in config().

Next steps

One agent for many units

A hotel chain served by a single agent, routed by WhatsApp number

Environments

How staging and production are separated