Adding Typed Configuration to a TypeScript Agent
Overview
TypeScript agents declare typed configuration with the config option on defineAgent(...). It is a single record of named fields, each a Standard Schema value (Zod / Valibot / ArkType / Effect Schema). At runtime the config is read through this.config inside a handler — one property per declared field, freshly read on each access, and fully typed from the schema.
Steps
- Declare a
configrecord ondefineAgent(...)— one schema per field - Read config via
this.config.<field>in handlers (each access reads the live value) - Set config in
golem.yamlor via CLI
Example
Agent with Config
import { z } from 'zod';
import { defineAgent, method } from '@golemcloud/golem-ts-sdk';
export const MyAgent = defineAgent({
name: 'MyAgent',
id: { name: z.string() },
// One config record; nested objects are supported and recursed field-by-field.
config: {
foo: z.number(),
bar: z.string(),
nested: z.object({
a: z.boolean(),
b: z.array(z.number()),
}),
},
methods: {
getFoo: method({ input: {}, returns: z.number() }),
describe: method({ input: {}, returns: z.string() }),
},
});
export const MyAgentImpl = MyAgent.implement({
init: () => ({}),
methods: {
getFoo() {
// `this.config` is statically typed from the config record — no casts,
// and `this.config.<typo>` is a compile error.
return this.config.foo;
},
describe() {
const n = this.config.nested;
return `${this.config.bar}:${n.a}:${n.b.join(',')}`;
},
},
});this.config is also available during init via the InitContext argument (init: (ctx) => ({ ... ctx.config.foo ... })).
Setting Config in golem.yaml
agents:
MyAgent:
config:
foo: 42
bar: "hello"
nested:
a: true
b: [1, 2, 3]Setting Config via CLI
golem agent new 'MyAgent("agent-1")' \
--config foo=42 \
--config bar=hello \
--config nested.a=trueConfig Cascade
Config values are resolved in order of increasing precedence:
componentTemplates → components → agents, with presets resolved within each template,
component, and agent layer, not as one final global layer.
Values set closer to the agent override those set at broader scopes.
Key Constraints
configis a single record ondefineAgent(...); each field is a Standard Schema value (not a class or interface with methods)- Read config through
this.config.<field>— each access reads the current value, so config changes between invocations are observed - Only object/record schemas are recursed into nested fields; unions, arrays, tuples, maps, and primitives are read whole
- Optional fields use the schema’s own optionality (e.g.
z.number().optional()) - Config keys in
golem.yamluse camelCase matching the field names - Config values are provisioned per environment (via
golem.yaml/ CLI); a caller may ALSO override non-secret config for a remote agent at call time viaDef.client.get(id, overrides)orDef.client.getPhantom(id, phantomId, overrides)(config-on-RPC — secret overrides are rejected) - If the config includes secret fields, mark them with
s.secret(...)and seegolem-add-secret-tsfor secret-specific declaration and CLI guidance