Getting Started with Kubiya Terraform Provider
This guide will walk you through setting up and using the Kubiya Control Plane Terraform Provider to manage your AI agent infrastructure as code.
Prerequisites
Before you begin, ensure you have:
- Terraform >= 1.0 installed (Download)
- Kubiya Control Plane Access (hosted or self-hosted)
- API Key from your Kubiya Control Plane
Step 1: Obtain Your API Key
For Hosted Control Plane (SaaS)
- Navigate to https://compose.kubiya.ai
- Go to Settings → API Keys
- Click Generate New API Key
- Copy and securely store your API key
For Self-Hosted Control Plane
- Access your self-hosted control plane dashboard
- Navigate to Settings → API Keys
- Generate and copy your API key
- Note your control plane base URL (e.g.,
https://control-plane.your-company.com)
Set up your authentication credentials:
Hosted Control Plane
export KUBIYA_CONTROL_PLANE_API_KEY="kcp_your_api_key_here"
Self-Hosted Control Plane
export KUBIYA_CONTROL_PLANE_API_KEY="kcp_your_api_key_here"
export KUBIYA_CONTROL_PLANE_BASE_URL="https://control-plane.your-company.com"
For production environments, consider using a secrets management solution like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault instead of environment variables.
Step 3: Create Your First Configuration
Create a new directory for your Terraform configuration:
mkdir kubiya-terraform
cd kubiya-terraform
Create a file named main.tf:
terraform {
required_version = ">= 1.0"
required_providers {
controlplane = {
source = "kubiya/control-plane"
version = "~> 1.0"
}
}
}
# Provider configuration
# Authentication is via environment variables
provider "controlplane" {
# KUBIYA_CONTROL_PLANE_API_KEY (required)
# KUBIYA_CONTROL_PLANE_BASE_URL (optional - defaults to https://control-plane.kubiya.ai)
}
# Create a production environment
resource "controlplane_environment" "production" {
name = "production"
display_name = "Production Environment"
description = "Production environment for AI agents"
tags = ["production", "managed-by-terraform"]
configuration = jsonencode({
region = "us-east-1"
max_workers = 10
auto_scaling = true
retention_days = 90
})
}
# Create a DevOps team
resource "controlplane_team" "devops" {
name = "devops-team"
description = "DevOps and platform engineering team"
# Runtime: "default" (Agno) or "claude_code" (Claude Code SDK)
runtime = "claude_code"
configuration = jsonencode({
max_agents = 10
slack_channel = "#devops-agents"
alert_on_error = true
})
}
# Create an operations agent
resource "controlplane_agent" "ops_assistant" {
name = "ops-assistant"
description = "AI agent for DevOps operations"
# Model options: "kubiya/claude-sonnet-4", "kubiya/gpt-4", etc.
model_id = "kubiya/claude-sonnet-4"
# Runtime: "default" or "claude_code"
runtime = "claude_code"
# Assign to team
team_id = controlplane_team.devops.id
# LLM configuration
llm_config = jsonencode({
temperature = 0.7
max_tokens = 4096
})
# Agent-specific configuration
configuration = jsonencode({
capabilities = ["kubernetes", "terraform", "monitoring"]
permissions = ["read", "execute"]
})
}
# Outputs for reference
output "environment_id" {
value = controlplane_environment.production.id
description = "Production environment ID"
}
output "team_id" {
value = controlplane_team.devops.id
description = "DevOps team ID"
}
output "agent_id" {
value = controlplane_agent.ops_assistant.id
description = "Operations assistant agent ID"
}
Initialize your Terraform working directory:
Expected output:
Initializing the backend...
Initializing provider plugins...
- Finding kubiya/control-plane versions matching "~> 1.0"...
- Installing kubiya/control-plane v1.0.0...
Terraform has been successfully initialized!
Step 5: Plan Your Changes
Preview what Terraform will create:
Review the planned changes carefully. You should see:
- 1 environment to create
- 1 team to create
- 1 agent to create
Step 6: Apply Your Configuration
Create the resources:
Type yes when prompted to confirm.
Expected output:
controlplane_environment.production: Creating...
controlplane_team.devops: Creating...
controlplane_environment.production: Creation complete after 2s [id=env-xxxxx]
controlplane_team.devops: Creation complete after 2s [id=team-xxxxx]
controlplane_agent.ops_assistant: Creating...
controlplane_agent.ops_assistant: Creation complete after 3s [id=agent-xxxxx]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
Outputs:
agent_id = "agent-xxxxx"
environment_id = "env-xxxxx"
team_id = "team-xxxxx"
Step 7: Verify Your Resources
Check the created resources:
# View outputs
terraform output
# View state
terraform show
You can also verify the resources in your Kubiya Control Plane dashboard.
Step 8: Make Changes
Update your configuration in main.tf. For example, change the agent description:
resource "controlplane_agent" "ops_assistant" {
name = "ops-assistant"
description = "Enhanced AI agent for DevOps operations" # Updated
# ... rest of configuration
}
Apply the changes:
terraform plan # Review changes
terraform apply # Apply changes
Using Data Sources
Look up existing resources using data sources. Create a file named data.tf:
# Look up an existing environment
data "controlplane_environment" "existing_prod" {
id = "env-xxxxx" # Use your actual environment ID
}
# Reference it in outputs
output "existing_env_name" {
value = data.controlplane_environment.existing_prod.name
}
# Use it to create dependent resources
resource "controlplane_agent" "another_agent" {
name = "data-analyst"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
# Reference the existing environment
configuration = jsonencode({
environment = data.controlplane_environment.existing_prod.name
})
}
Best Practices for Operators
1. Use Variables
Create variables.tf:
variable "environment" {
description = "Environment name (dev, staging, production)"
type = string
default = "production"
}
variable "team_name" {
description = "Team name"
type = string
}
variable "agent_model" {
description = "LLM model for agents"
type = string
default = "kubiya/claude-sonnet-4"
}
Create terraform.tfvars:
environment = "production"
team_name = "platform-engineering"
agent_model = "kubiya/claude-sonnet-4"
2. Use Remote State
Configure remote state storage in backend.tf:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "kubiya/production/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
3. Organize with Modules
Create reusable modules:
modules/
agent-team/
main.tf
variables.tf
outputs.tf
environments/
production/
main.tf
staging/
main.tf
4. Use Workspaces
Manage multiple environments:
# Create workspaces
terraform workspace new production
terraform workspace new staging
# Switch between workspaces
terraform workspace select production
terraform apply
terraform workspace select staging
terraform apply
Cleanup
When you’re done experimenting, destroy the resources:
Type yes when prompted.
Be careful with terraform destroy in production environments. Consider using -target to destroy specific resources or implement lifecycle rules to prevent accidental deletion.
Troubleshooting
Authentication Errors
If you see authentication errors:
# Verify environment variables are set
echo $KUBIYA_CONTROL_PLANE_API_KEY
echo $KUBIYA_CONTROL_PLANE_BASE_URL
# Re-export if needed
export KUBIYA_CONTROL_PLANE_API_KEY="your-key"
Provider Not Found
If Terraform can’t find the provider:
# Clear cache and reinitialize
rm -rf .terraform .terraform.lock.hcl
terraform init
Resource Already Exists
If resources already exist:
# Import existing resources
terraform import controlplane_agent.ops_assistant agent-xxxxx
Next Steps
Now that you have a basic configuration running:
- Configure Provider Options - Learn about advanced configuration
- Explore Resources - Detailed documentation for all resources
- Review Examples - End-to-end examples for operators
- Learn About Policies - Implement governance with OPA Rego
- Set Up Jobs - Automate workflows with scheduled jobs
Additional Resources