All execution behavior is controlled through the AmpSdk.Types.Options struct.

For model selection specifically, Amp is payload-only in this repo today:

  • AmpSdk.Types.Options can carry a shared core model_payload
  • AmpSdk.Types.Options.validate!/1 canonicalizes that payload when present
  • there is no separate raw model/backend option surface in amp_sdk
  • if no payload is supplied, the Amp SDK does not invent a repo-local model fallback path

Options Reference

FieldTypeDefaultDescription
cwdString.t()File.cwd!()Working directory for the Amp agent
modeString.t()"smart"Agent mode (see below)
dangerously_allow_allboolean()falseSkip all permission prompts
visibilityString.t()"workspace"Thread visibility
continue_threadboolean | String.t()nilContinue a thread
settings_fileString.t()nilPath to settings.json
log_levelString.t()nilLog level for the CLI
log_fileString.t()nilLog output file path
envmap()%{}Extra environment variables
mcp_configmap() | String.t()nilMCP server configuration
toolboxString.t()nilPath to toolbox scripts
skillsString.t()nilPath to custom skills
permissions[Permission.t()]nilPermission rules
labels[String.t()]nilThread labels (max 20)
thinkingboolean()falseUse --stream-json-thinking for string prompts
model_payloadSelection.t() | map() | nilnilShared core model-selection payload
execution_surfaceExecutionSurface.t() | map() | keyword() | nilnilShared core execution surface for local or SSH placement
stream_timeout_mspos_integer()300_000Stream receive timeout in milliseconds
no_ideboolean()falseDisable IDE context injection (--no-ide)
no_notificationsboolean()falseDisable sound notifications (--no-notifications)
no_colorboolean()falseDisable ANSI colors (--no-color)
no_jetbrainsboolean()falseDisable JetBrains integration (--no-jetbrains)

Shared Core Model Payload

When you want an explicit model selection, build it through cli_subprocess_core and pass the resolved payload through Options:

{:ok, payload} =
  CliSubprocessCore.ModelRegistry.build_arg_payload(:amp, "amp-1", [])

AmpSdk.run("Review this patch", %Options{model_payload: payload})

AmpSdk.Types.Options.validate!/1 canonicalizes either a real CliSubprocessCore.ModelRegistry.Selection or a Map.from_struct(payload) shape back into the same selection struct. Forward-compatible extra fields stay attached to the payload instead of being nested under :extra.

Shared Core Execution Surface

When you need SSH placement or other shared-core transport routing, pass an execution surface through Options.execution_surface as a struct, map, or keyword list:

alias AmpSdk.Types.Options
alias CliSubprocessCore.ExecutionSurface

surface = %ExecutionSurface{
  surface_kind: :ssh_exec,
  transport_options: [destination: "build-host.example"]
}

AmpSdk.run("Inspect the remote workspace", %Options{execution_surface: surface})

Amp normalizes all three public forms into the canonical shared-core struct
during `Options.validate!/1`.

On remote SSH surfaces, local `AMP_CLI_PATH` overrides are intentionally
ignored. The remote host is expected to expose `amp` on its own `PATH`, or to
receive a remote `PATH` override through `Options.env`. Missing remote binaries
surface as structured `:cli_not_found` errors with the remote stderr attached.

Agent Modes

ModeSDK CompatibleDescription
"smart"YesDefault — balanced model and tool selection
"rush"NoFaster execution, incompatible with --stream-json
"deep"NoThorough analysis, incompatible with --stream-json
"free"NoInteractive-only, incompatible with --execute

Important: Only "smart" mode supports --stream-json, which the SDK uses for both execute/2 and run/2. The other modes (rush, deep) are only usable via the CLI directly (for example amp --mode deep --execute "prompt" without --stream-json). "free" mode is interactive-only and cannot be used programmatically at all. This is a CLI restriction, not an SDK limitation.

# Default smart mode (the only mode that works with the SDK)
AmpSdk.execute("Explain this code") |> Enum.each(&handle/1)
{:ok, result} = AmpSdk.run("Explain this code")

mode is passed through to the installed Amp CLI. Supported values may change as Amp evolves.

Thread Visibility

ValueDescription
"private"Only you can see the thread
"public"Anyone with the link can view
"workspace"Visible to workspace members
"group"Visible to group members

Thread Continuation

# Continue the most recent thread
AmpSdk.run("Follow up", %Options{continue_thread: true})

# Continue a specific thread
AmpSdk.run("Follow up", %Options{continue_thread: "T-abc123"})

MCP Server Configuration

Pass MCP server configs as a map:

mcp = %{
  filesystem: %{
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-filesystem"],
    env: %{}
  }
}

AmpSdk.run("List files", %Options{mcp_config: mcp})

Environment Variables

VariablePurpose
AMP_CLI_PATHOverride CLI binary path
AMP_API_KEYAmp authentication key
AMP_URLOverride Amp service endpoint (default: https://ampcode.com/)
AMP_TOOLBOXPath to toolbox scripts; prefer Options.toolbox for per-run control
AMP_SDK_VERSIONSDK identifier (auto-set to elixir-<current package version>)
AMP_LOG_LEVELLog level (alternative to --log-level flag)
AMP_LOG_FILELog file path (alternative to --log-file flag)
AMP_SETTINGS_FILESettings file path (alternative to --settings-file flag)

AmpSdk.run/2 and AmpSdk.execute/2 share the same environment construction path: explicit per-run overrides, optional :amp_sdk, :base_env application config or caller-supplied base env maps, and automatic AMP_SDK_VERSION injection. Provider behavior keys such as AMP_API_KEY, AMP_URL, AMP_LOG_LEVEL, AMP_LOG_FILE, and AMP_SETTINGS_FILE are not ambiently forwarded by the runtime path. Pass provider behavior environment explicitly through Options.env or the typed option when applicable.

Governed execution is a separate mode selected by explicit authority. It rejects Options.env, AMP_CLI_PATH, AMP_API_KEY, AMP_URL, log/settings file paths, permissions/skills settings, MCP config, MCP OAuth credential options, cwd overrides, and execution-surface overrides. The governed process receives only the authority-materialized command, cwd, and env.

Additional env vars per execution:

AmpSdk.run("check env", %Options{env: %{"MY_VAR" => "value"}})

nil values in Options.env are dropped during normalization (they are not coerced into empty-string values).

Headless Flags

Control IDE, notification, color, and JetBrains integration:

AmpSdk.run("task", %Options{
  no_ide: true,            # --no-ide (disable IDE file inclusion)
  no_notifications: true,  # --no-notifications (silence sounds)
  no_color: true,          # --no-color (plain text output)
  no_jetbrains: true       # --no-jetbrains (disable JetBrains)
})

These default to false. Set to true for headless/CI environments.

Option Key Normalization

When building MCP structs from maps/keywords, use atom keys for option fields.

# Valid: atom keys
AmpSdk.Types.MCPStdioServer.new(%{command: "npx", args: ["-y", "tool"]})

String keys are ignored by these constructors. If you already have JSON-style string keys, pass Options.mcp_config as a JSON string instead of a map.

For MCP constructors, nil values inside env and headers maps are dropped during normalization.

Thinking Mode

Include the model's chain-of-thought reasoning in responses:

AmpSdk.execute("Explain this code", %Options{thinking: true})
|> Enum.each(fn
  %AmpSdk.Types.AssistantMessage{message: %{content: content}} ->
    for %AmpSdk.Types.ThinkingContent{thinking: t} <- content, do: IO.puts("[think] #{t}")
    for %AmpSdk.Types.TextContent{text: t} <- content, do: IO.write(t)
  _ -> :ok
end)

CLI Discovery

The SDK locates the Amp CLI by checking (in order):

  1. Materialized AMP_CLI_PATH from :cli_subprocess_core, :provider_cli_env
  2. ~/.amp/bin/amp
  3. ~/.local/bin/amp
  4. System PATH

This discovery order is standalone direct-use behavior only. Governed execution bypasses it and launches the authority-materialized command.

Top-level applications that want to honor OS environment variables should read them in config/runtime.exs or another configuration boundary and put the resulting map in :cli_subprocess_core, :provider_cli_env; amp_sdk runtime modules do not call System.get_env/1.

Use AmpSdk.CLI.resolve/1 to inspect the command spec:

{:ok, spec} = AmpSdk.CLI.resolve()
IO.inspect(spec.program, label: "program")
IO.inspect(spec.argv_prefix, label: "argv prefix")

Advanced CLI Settings via settings_file

The Amp CLI supports many settings beyond what the SDK exposes as Options fields. You can access all of them by pointing Options.settings_file to a JSON file:

AmpSdk.run("task", %Options{settings_file: "/path/to/settings.json"})

When you also provide Options.permissions or Options.skills, the SDK merges those into your settings file automatically.

Available Settings

These are the amp. prefix keys recognized by the CLI. All can be set in the settings JSON:

SettingTypeDescription
amp.proxystringHTTP/HTTPS proxy URL for requests to Amp servers
amp.network.timeoutintegerSeconds to wait for network requests before timeout
amp.tools.disable[string]Tool names to disable (use builtin:name to target only builtins)
amp.tools.enable[string]Glob patterns of tools to enable (if set, only matching tools are active)
amp.guardedFiles.allowlist[string]File glob patterns allowed without confirmation (overrides built-in denylist)
amp.mcpServersobjectMCP server configurations (alternative to Options.mcp_config)
amp.permissions[object]Permission rules (alternative to Options.permissions)
amp.dangerouslyAllowAllbooleanSkip all prompts (alternative to Options.dangerously_allow_all)
amp.skills.pathstringPath to custom skills (alternative to Options.skills)
amp.toolbox.pathstringPath to toolbox scripts (alternative to Options.toolbox)
amp.notifications.enabledbooleanEnable sound notifications
amp.notifications.system.enabledbooleanEnable system notifications when terminal unfocused
amp.git.commit.coauthor.enabledbooleanAdd Amp as co-author in git commits
amp.git.commit.ampThread.enabledbooleanAdd Amp-Thread trailer in git commits
amp.showCostsbooleanShow cost tracking during thread execution
amp.fuzzy.alwaysIncludePaths[string]Globs always included in fuzzy file search (even if gitignored)
amp.bitbucketTokenstringPersonal access token for Bitbucket Enterprise
amp.experimental.modes[string]Enable experimental agent modes by name

Example: Enterprise Configuration

# Write a settings file for enterprise use
settings = %{
  "amp.proxy" => "http://proxy.corp.example.com:8080",
  "amp.network.timeout" => 60,
  "amp.tools.disable" => ["browser_navigate"],
  "amp.guardedFiles.allowlist" => ["config/**"],
  "amp.git.commit.coauthor.enabled" => true
}

path = Path.join(System.tmp_dir!(), "amp-settings.json")
File.write!(path, Jason.encode!(settings))

{:ok, result} = AmpSdk.run("Review the code", %Options{settings_file: path})