Configuration and Secrets
Before Golem 1.5, agents could only receive configuration through environment variables — string-only values that were not discoverable or type-checked. Golem 1.5 introduces code-first typed configuration and secrets that become part of an agent’s type. This means deployment can verify that all required configuration values are provided with proper types before the agent starts.
Configuration
Configuration types are defined as records in your agent’s source code and can be nested. The SDK makes configuration available to the implementation: Rust and Scala use a constructor-injected Config wrapper, while Effect TypeScript uses a service created with defineConfig.
TypeScript
import { z } from 'zod';
import { defineAgent, method } from '@golemcloud/golem-ts-sdk';
export const ExampleAgent = defineAgent({
name: 'ExampleAgent',
id: { exampleParam: z.string() },
config: {
debugLogs: z.boolean(),
alias: z.string().optional(),
database: z.object({
host: z.string(),
port: z.number(),
}),
},
methods: {
useConfig: method({ input: {}, returns: z.void() }),
},
});
export const ExampleAgentImpl = ExampleAgent.implement({
init: () => ({}),
methods: {
useConfig() {
// `this.config` is read fresh on each access and typed from the config record.
if (this.config.debugLogs) {
console.debug("Debug logs enabled");
}
},
},
});Providing configuration in golem.yaml
Configuration values are specified in golem.yaml under the config section for each agent:
agents:
ExampleAgent:
config:
debugLogs: true
database:
host: localhost
port: 5432Secrets
Secrets are a special type of configuration — they are stored per environment and can be updated dynamically without redeploying the agent. Mark secret fields using your SDK’s secret type or schema, as shown below:
TypeScript
// Import the `s` schema helper: import { s } from '@golemcloud/golem-ts-sdk';
password: s.secret(z.string())Accessing secrets
Unlike regular configuration values, secret fields hold an opaque handle until the agent explicitly accesses the secret. The reveal happens at that call site, so secret material is not embedded in the typed config value. Each reveal pins the secret revision it resolved; retries and replay use that pinned revision deterministically, while a fresh access after a secret update can observe the new value.
In Effect TypeScript, evaluate yield* config.apiKey.get inside an Effect generator. It returns a Redacted<string>; use Redacted.value(apiKey) only at the boundary that requires plaintext.
Managing secrets via CLI
Use the golem secret CLI commands to manage secrets:
golem secret create db.password --type string --value "pwd"
golem secret list
golem secret update db.password --value "new-pwd"
golem secret delete db.passwordWhen no value option is given, create and update prompt for the value with hidden input. To keep the value out of the shell history, it can also be read from STDIN with --value-stdin. golem secret create --update-existing updates the value of an existing secret instead of failing, golem secret update --unset removes the value, and golem secret delete asks for confirmation unless --yes is given.
Secret defaults in golem.yaml
You can define default secret values per environment in golem.yaml, nested by secret path. The {{ X }} syntax resolves environment variables from the user’s system at deploy time:
secretDefaults:
local:
db:
password: "{{ DB_PASSWORD }}"Defaults are only applied to secrets that do not exist yet in the environment, so the referenced environment variables are only required when a secret gets created.