# Golem Add Secret Moonbit

> Adding secrets to MoonBit Golem agents. Use when the user asks to add secret values, API keys, or sensitive configuration to a MoonBit agent.

- Skill: `golemcloud/golem-add-secret-moonbit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add golemcloud/golem-add-secret-moonbit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/golemcloud/golem-add-secret-moonbit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: golemcloud (https://skillmd.com/u/golemcloud)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/golemcloud/golem-add-secret-moonbit

---


# 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, the config value carries an opaque secret handle and plaintext is revealed only when agent code calls `.get!()`. 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:

```moonbit
#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:

```moonbit
#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 explicitly reveal the value. Secrets are lazily loaded, so a fresh `.get!()` call can observe updated values after the update is visible:

```moonbit
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.

```shell
# Create secrets in the current environment
golem secret create apiKey --secret-type String --secret-value "sk-abc123"
golem secret create db.password --secret-type String --secret-value "s3cret"

# List all secrets
golem secret list

# Update a secret value
golem secret update-value apiKey --secret-value "new-value"

# Delete a secret
golem 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:

```yaml
secretDefaults:
  local:
    apiKey: "dev-key-123"
    db:
      password: "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 skill
- 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 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 revealed on `.get!()`, and each reveal pins the resolved secret revision for deterministic retries and replay
- Fresh `.get!()` calls can observe runtime updates without restarting the agent
- `.get!()` raises `@common.AgentError` — use MoonBit's error handling (`!` or `try`) accordingly
- **Never edit generated files** — `golem_reexports.mbt`, `golem_agents.mbt`, and `golem_derive.mbt` are auto-generated by `golem build`

