Welcome to the new Golem Cloud Docs! 👋
Adding Secrets to a MoonBit Agent

Adding Secrets to a MoonBit Agent

Overview

Secrets are sensitive configuration values (API keys, passwords, tokens) stored per-environment and accessed at runtime via @config.Secret[T] from the Golem MoonBit SDK. Unlike regular config fields, secrets are not stored in golem.yaml (which is checked into source control). They are managed via the CLI or through secretDefaults for local development.

Declaring Secrets in a Config Struct

Use @config.Secret[T] for secret fields inside a #derive.config struct:

#derive.config
pub(all) struct MyAgentConfig {
  name : String
  api_key : @config.Secret[String]
  db : DbConfig
}

#derive.config
pub(all) struct DbConfig {
  host : String
  port : UInt
  password : @config.Secret[String]
}

Wiring Secrets Into The Agent Constructor

Secrets use the same typed config mechanism as regular agent config. Receive the config via @config.Config[T] in the constructor:

#derive.config
pub(all) struct MyAgentConfig {
  api_key : @config.Secret[String]
}

#derive.agent
struct MyAgent {
  config : @config.Config[MyAgentConfig]
}

fn MyAgent::new(config : @config.Config[MyAgentConfig]) -> MyAgent {
  { config, }
}

pub fn MyAgent::connect(self : Self) -> String {
  let api_key = self.config.value.api_key.get!()
  "using \{api_key}"
}
  • The @config.Config[T] parameter in the constructor is detected automatically by the SDK tooling to embed config and secret declarations into the component metadata.

Reading Secrets at Runtime

Call .get!() on a Secret[T] to retrieve the value. Secrets are lazily loaded, so updated values are picked up on the next .get!() call:

pub fn MyAgent::connect(self : Self) -> String {
  let config = self.config.value
  let api_key = config.api_key.get!()
  let db_password = config.db.password.get!()
  "Connecting to \{config.db.host}:\{config.db.port} with key \{api_key}"
}

Managing Secrets via CLI

Secrets are environment-scoped — each deployment environment has its own set of secret values.

# Create secrets in the current environment
golem agent-secret create apiKey --secret-type String --secret-value "sk-abc123"
golem agent-secret create db.password --secret-type String --secret-value "s3cret"
 
# List all secrets
golem agent-secret list
 
# Update a secret value
golem agent-secret update-value apiKey --secret-value "new-value"
 
# Delete a secret
golem agent-secret delete apiKey

Note: For update-value and delete, you can also use --id <uuid> instead of the positional path.

Secret Defaults in golem.yaml

For local development convenience, set defaults under secretDefaults. These are not used in production environments:

secretDefaults:
  local:
    - path: [apiKey]
      value: "dev-key-123"
    - path: [db, password]
      value: "dev-password"

Key Points

  • Secrets use the same @config.Config[T] constructor injection mechanism as regular typed config
  • If the agent also needs non-secret typed config guidance, use golem-add-config-moonbit alongside this guide
  • Secret paths are normalized to camelCase by the platform — MoonBit snake_case field names like api_key become apiKey in the CLI and manifest (e.g., golem agent-secret create apiKey ...)
  • The --secret-type argument accepts type names using the project's language syntax (e.g., String, UInt, Bool) or JSON-encoded analysed types as a fallback
  • Secrets are stored per-environment, not per-agent-instance
  • Missing required secrets cause agent creation/deployment to fail
  • Secrets are lazily loaded on .get!(), allowing runtime updates without restarting the agent
  • .get!() raises @common.AgentError — use MoonBit's error handling (! or try) accordingly
  • Never edit generated filesgolem_reexports.mbt, golem_agents.mbt, and golem_derive.mbt are auto-generated by golem build