This is an experimental, community-built project intended solely for learning, experimentation, and prototyping. It is NOT intended, tested, or supported for production use.
It is provided "AS IS", without warranty of any kind, express or implied. You use it entirely at your own risk. The author(s) and contributors accept no liability for any damage, data loss, downtime, cost, security incident, or other harm arising from its use. The "1.0.0" version number denotes API/schema stability under SemVer — it is not a statement of production-readiness or fitness for any purpose.
See the LICENSE (MPL 2.0, sections 6 & 7) for the full warranty disclaimer and limitation of liability.
A Terraform / OpenTofu provider for Anthropic Claude Managed Agents — declaratively manage agents (with tools, MCP servers, skills, and multiagent coordination), environments, vaults, custom skills, and memory stores from Terraform configurations.
Unofficial. This is a community project. It is not maintained by, endorsed by, or affiliated with Anthropic. Upstream API: Claude Managed Agents docs.
A community-maintained Terraform / OpenTofu provider for the Anthropic Claude Managed Agents API. Resources and data sources:
- Agents — with nested HCL for
tools(agent_toolset_20260401,mcp_toolset,custom),mcp_servers,skills, andmultiagentcoordination - Environments — cloud and dedicated, with
apt/npm/pippackage install - Vaults and vault credentials — secrets handled via Terraform 1.11 write-only attributes (not persisted to state)
- Custom skills — multipart upload, content-hash drift detection, immutable versions
- Memory stores — persistent agent memory, attached at session time
The Managed Agents API is distinct from the standard Anthropic Messages API. This provider does not manage the Messages API or generic /v1/messages calls.
Claude Managed Agents is Anthropic's hosted runtime for long-running, tool-using agents. The platform exposes a REST API for creating and configuring those agents and their supporting resources (environments, vaults, memory stores).
This provider lets you put that configuration under Terraform so you can:
- Review changes in pull requests instead of via ad-hoc API calls.
- Version-control your agent definitions alongside the rest of your infra.
- Promote agents across workspaces with the same workflow you use for everything else.
| Capability | Status |
|---|---|
Resource + data source claude-managed-agents_agent (flat fields: name, model, system, description, metadata) |
shipped |
Agent nested HCL: tools (agent_toolset_20260401, mcp_toolset, custom), mcp_servers, skills, multiagent |
shipped |
Resource + data source claude-managed-agents_environment |
shipped |
Resource + data source claude-managed-agents_vault |
shipped |
Resource + data source claude-managed-agents_vault_credential (TF 1.11 write-only secrets) |
shipped |
Resource + data source claude-managed-agents_memory_store |
shipped |
Resource claude-managed-agents_skill (multipart upload, content-hash drift detection, 30 MB cap) |
shipped |
Resource + data source claude-managed-agents_deployment (scheduled/manual, pause-resume via desired_status, write-only github token) |
shipped |
Data source claude-managed-agents_deployment_runs (run audit records, typed error taxonomy) |
shipped |
Data source claude-managed-agents_skill (prebuilt + custom) |
shipped |
Data source claude-managed-agents_agent_version |
shipped |
Data source claude-managed-agents_file |
shipped |
For per-release change history (including deprecations and breaking changes), see CHANGELOG.md.
terraform {
required_version = ">= 1.11"
required_providers {
claude-managed-agents = {
source = "modus-agendi/anthropic-claude-managed-agents"
version = "~> 1.0"
}
}
}Don't rename
claude-managed-agentsto something shorter. That string is the prefix on every resource type (claude-managed-agents_agent,claude-managed-agents_vault, …). If you alias it (e.g. toanthropic), every resource block must add an explicitprovider = claude-managed-agentsargument — noisier than keeping the literal name.
provider "claude-managed-agents" {
# api_key defaults to the ANTHROPIC_API_KEY environment variable.
}
resource "claude-managed-agents_agent" "coding_assistant" {
name = "Coding Assistant"
model = "claude-opus-4-7"
system = "You are a helpful coding agent."
description = "Pairs on Go and Terraform tasks."
metadata = {
team = "platform"
}
}
output "agent_id" {
value = claude-managed-agents_agent.coding_assistant.id
}export ANTHROPIC_API_KEY="sk-ant-..."
terraform init
terraform applyThe provider reads credentials from, in order of precedence:
- The
auth_tokenorapi_keyargument on theproviderblock (set only one). - The
ANTHROPIC_AUTH_TOKENenvironment variable: an OAuth or federated access token, sent asAuthorization: Bearer. - The
ANTHROPIC_API_KEYenvironment variable, sent asx-api-key.
Both api_key and auth_token are marked Sensitive in the schema, so they are redacted from plan/apply output. Provider configuration is not written to Terraform state, so the credential never lands in the state file regardless of how you supply it. The risk of hardcoding it in the provider block is that it then lives in your configuration files (and version control), and can surface in TF_LOG debug or crash logs — so prefer the ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY environment variable in production and CI.
claude-managed-agents_vault_credential uses Terraform 1.11 write-only attributes for its secret fields (token, access_token, refresh_token, client_secret): these values are never persisted to state. Rotate by incrementing the matching *_wo_version integer.
provider "claude-managed-agents" {
api_key = var.anthropic_api_key # only set this if env var is impractical
base_url = "https://api.anthropic.com"
max_retries = 3
}| Kind | Name | Docs |
|---|---|---|
| Resource | claude-managed-agents_agent |
docs/resources/agent.md |
| Resource | claude-managed-agents_deployment |
docs/resources/deployment.md |
| Resource | claude-managed-agents_environment |
docs/resources/environment.md |
| Resource | claude-managed-agents_memory_store |
docs/resources/memory_store.md |
| Resource | claude-managed-agents_skill |
docs/resources/skill.md |
| Resource | claude-managed-agents_vault |
docs/resources/vault.md |
| Resource | claude-managed-agents_vault_credential |
docs/resources/vault_credential.md |
| Data source | claude-managed-agents_agent |
docs/data-sources/agent.md |
| Data source | claude-managed-agents_agent_version |
docs/data-sources/agent_version.md |
| Data source | claude-managed-agents_deployment |
docs/data-sources/deployment.md |
| Data source | claude-managed-agents_deployment_runs |
docs/data-sources/deployment_runs.md |
| Data source | claude-managed-agents_environment |
docs/data-sources/environment.md |
| Data source | claude-managed-agents_file |
docs/data-sources/file.md |
| Data source | claude-managed-agents_memory_store |
docs/data-sources/memory_store.md |
| Data source | claude-managed-agents_skill |
docs/data-sources/skill.md |
| Data source | claude-managed-agents_vault |
docs/data-sources/vault.md |
| Data source | claude-managed-agents_vault_credential |
docs/data-sources/vault_credential.md |
- Deployments: scheduling and running agents — scheduled vs manual runs, the
desired_status/statussplit, mounting resources, reading run history, and the caveats to know before relying on deployments. - State security and remote backends — what is and isn't in state, and encrypted/locked backends (S3+KMS, GCS, Terraform Cloud).
- Secrets management and rotation — write-only attributes and the rotation ceremony for vault credentials and deployment github tokens.
- Import and state recovery —
terraform importper resource, the composite vault-credential id, and re-supplying write-only fields after import. - Drift detection and remediation —
plan -refresh-only -detailed-exitcode, the provider's expected-drift patterns, andignore_changesguidance. - Upgrading and migration — version constraints, the registry slug/namespace history, and a safe upgrade procedure.
- Agent destroy maps to archive. The upstream API has no
DELETE /v1/agents/{id}endpoint.terraform destroyissuesPOST /v1/agents/{id}/archive. Archived agents are read-only and cannot be unarchived. versionis server-managed. The provider passes it along on update for optimistic concurrency. If you see version conflicts in plans, refresh the state withterraform apply -refresh-only.metadatais key-level merged. The upstream API uses merge semantics: removing a key from your HCL causes the provider to send JSON null for that key, which the API treats as a delete. Applies to bothclaude-managed-agents_agent.metadataandclaude-managed-agents_vault.metadata.- Environments are immutable. The API has no environment update endpoint, so every attribute on
claude-managed-agents_environmentisForceNew. Any change triggers replacement. Destroy issuesDELETE /v1/environments/{id}and falls back to archive if the API returns 409 (active session reference). - Vault and memory_store destroy archives by default. Set
delete_on_destroy = trueon the resource to hard-delete instead. Vault archive cascades through credentials; memory_store hard-delete cascades through memories and memory versions. - Deployment pause/resume is driven by
desired_status, notstatus. Setdesired_statustoactiveorpaused; the provider reconciles via the pause/resume endpoints.desired_statusis your intent and is deliberately decoupled from the observedstatus: when the API auto-pauses a deployment on error,statusbecomespausedwhiledesired_statusstaysactive, and Terraform will not fight it (no resume flap). Inspectpaused_reason, fix the cause, then re-apply to resume. Editinginitial_eventsforces replacement (the API does not patch events in place). Destroy archives the deployment (one-way; no DELETE endpoint). The githubauthorization_tokeninresourcesis write-only — bumpauthorization_token_wo_versionto re-send it on rotation. - Vault-credential secrets are write-only. Secret fields are never read back from the API. Rotate by incrementing the corresponding
token_wo_version,access_token_wo_version,refresh_token_wo_version, orclient_secret_wo_versioninteger.auth.type,auth.mcp_server_url,auth.refresh.token_endpoint, andauth.refresh.client_idare immutable (RequiresReplace).
The provider builds on protocol v6 and uses the Plugin Framework. It requires Terraform 1.11+ or OpenTofu 1.8+ — both engines support TF 1.11 write-only attributes, which the provider uses to handle secrets in claude-managed-agents_vault_credential.
Pre-requisites: Go 1.23+, Terraform 1.11+ (or OpenTofu 1.8+), golangci-lint.
git clone https://github.com/modus-agendi/terraform-provider-anthropic-claude-managed-agents
cd terraform-provider-anthropic-claude-managed-agents
go mod download
make test # unit tests
make testacc # acceptance tests, httptest fixture (free)
make testacc-live # acceptance tests against api.anthropic.com (requires ANTHROPIC_API_KEY)
# Behavioral scenarios (L5) — opens real sessions and grades them via an
# LLM-as-judge call. Bills real inference tokens; see
# internal/scenarios/README.md for cost notes.
TF_ACC_SCENARIOS=1 go test ./internal/scenarios/... -count=1 -timeout 10m -v
make lint
make docs # regenerate docs/ via tfplugindocs
make coverage-html # full coverage profile + HTML report
make coverage-split # mirrors CI: split unit + acceptance profiles
make pr # full local PR-check pipeline (mirrors CI)
make install # build + install into ~/.terraform.d/plugins/...Once installed locally, pin the dev version in your test main.tf:
terraform {
required_providers {
claude-managed-agents = {
source = "modus-agendi/anthropic-claude-managed-agents"
version = "0.0.1-dev"
}
}
}Gotcha —
make installshadows registry releases.make installcopies the binary into~/.terraform.d/plugins/registry.terraform.io/modus-agendi/anthropic-claude-managed-agents/, which Terraform treats as the authoritative version source. Any external config that pins a different version (e.g.version = "~> 0.2") will failterraform initwith "no available releases match the given constraints". Runrm -rf ~/.terraform.d/plugins/registry.terraform.io/modus-agendito drop back to registry-pulled releases.
Testing runs in five layers so that cheap, deterministic checks gate every PR while the expensive, real-API checks run on a schedule. Full details (and the exact CI triggers) are in CONTRIBUTING.md.
| Layer | What it checks | Real API | Runs |
|---|---|---|---|
| L1 Unit | client methods in isolation | no | every PR (race + coverage) |
| L2 Integration | the provider against an in-process fake API | no | every PR, TF 1.11/1.12/latest |
| L3 Live acceptance | the same provider suite against api.anthropic.com |
yes | manual + nightly + release gate |
| L4 Sweeper | archives orphaned tf-acc-test-* resources |
yes (archive only) | around L3/L5 |
| L5 Behavioral scenarios | does a provisioned agent actually do the task? | yes (real sessions + LLM-as-judge) | manual + nightly + release gate |
L5 is the unusual one and worth calling out for transparency. It provisions
resources via Terraform, opens a real session, captures the full event
trajectory, asserts deterministic properties on it, then has a separate judge
model grade the final answer against a rubric. It bills real inference
tokens — roughly $0.05–$0.20 per scenario (the current catalog of six runs
at about $0.68 total). It is a hard gate on releases: a scenario FAIL
blocks goreleaser unless explicitly skipped. See
internal/scenarios/README.md for the scenario
format, the deployment/lifecycle scenario kinds, and a note on the undocumented
manual-run endpoint the harness relies on.
Coverage target is 85% (codecov gates at 70% project / 75% patch). Coverage
is treated as a gap-finder, not a goal — see CLAUDE.md.
The provider follows Semantic Versioning. As of v1.0.0 the resource and data-source schema is stable: breaking changes happen only in a new major version (2.0.0), never in a minor or patch release. Pin version = "~> 1.0" to receive non-breaking 1.x updates automatically. Breaking changes, when a 2.0 eventually happens, will be called out in CHANGELOG.md with a migration note.
A breaking change is one of:
- Removing or renaming a schema attribute.
- Changing the type of a schema attribute.
- Changing the required/optional/computed status of an attribute in a way that affects existing configurations.
- Changing the default value of an attribute.
Under consideration for the next minor: an ephemeral resource for vault-credential validation, optional skill version retention attributes, and broadening the L5 behavioral scenario catalog. Sessions, dreams, memory contents/versions, and webhook endpoints are not currently on the roadmap. Open an issue if you'd like to discuss.
See CONTRIBUTING.md.
- SECURITY.md — how to report vulnerabilities privately.
- CODE_OF_CONDUCT.md — expected conduct for contributors and maintainers.
- Issue templates — structured bug reports and feature requests.
- Pull request template — checklist for opening a PR.
- CODEOWNERS — review routing.
Distributed under the Mozilla Public License 2.0. See LICENSE for the full text (add the file via the GitHub UI's license picker if it's missing from a fresh checkout).
This is a community-maintained project. It is not affiliated with Anthropic. "Claude" is a trademark of Anthropic; usage here is descriptive, identifying the API this provider integrates with.