Documentation Index
Fetch the complete documentation index at: https://docs.kubiya.ai/llms.txt
Use this file to discover all available pages before exploring further.
Terraform Data Sources
Data sources allow you to query existing Kubiya Control Plane resources and use their attributes in your Terraform configurations.
Why Use Data Sources?
- Reference Existing Resources: Look up resources created outside Terraform
- Cross-Stack References: Reference resources from other Terraform configurations
- Dynamic Configuration: Build configurations based on existing infrastructure
- Read-Only Access: Query resources without managing them
Available Data Sources
All managed resources have corresponding data sources:
controlplane_environment - Look up a single environment by ID
controlplane_project - Look up a single project by ID
controlplane_team - Look up a single team by ID
controlplane_agent - Look up a single agent by ID
controlplane_skill - Look up a single skill by ID
controlplane_policy - Look up a single policy by ID
controlplane_job - Look up a single job by ID
controlplane_jobs - List all jobs
controlplane_worker_queue - Look up a single worker queue by ID
controlplane_worker_queues - List all worker queues in an environment
Data Source Arguments
All data sources require the resource id:
data "controlplane_<resource>" "<name>" {
id = "<resource-id>"
}
Data Source Examples
controlplane_environment
Look up an existing environment by ID:
data "controlplane_environment" "production" {
id = "env-xxxxx"
}
# Use the data source
output "production_env_name" {
value = data.controlplane_environment.production.name
}
output "production_env_config" {
value = data.controlplane_environment.production.configuration
}
# Reference in other resources
resource "controlplane_agent" "new_agent" {
name = "agent-in-${data.controlplane_environment.production.name}"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
configuration = jsonencode({
environment = data.controlplane_environment.production.name
})
}
Exported Attributes:
id - Environment ID
name - Environment name
display_name - Display name
description - Environment description
tags - List of tags
configuration - Environment configuration (JSON)
execution_environment - Execution settings (JSON)
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_project
Look up an existing project:
data "controlplane_project" "ml_platform" {
id = "project-xxxxx"
}
output "project_info" {
value = {
name = data.controlplane_project.ml_platform.name
key = data.controlplane_project.ml_platform.key
}
}
# Use in agent configuration
resource "controlplane_agent" "ml_agent" {
name = "ml-agent"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
configuration = jsonencode({
project = data.controlplane_project.ml_platform.name
})
}
Exported Attributes:
id - Project ID
name - Project name
key - Project key
description - Project description
goals - Project goals
visibility - Visibility setting
metadata - Project metadata (JSON)
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_team
Look up an existing team:
data "controlplane_team" "devops" {
id = "team-xxxxx"
}
# Create agent in existing team
resource "controlplane_agent" "new_devops_agent" {
name = "new-devops-agent"
description = "New agent for ${data.controlplane_team.devops.name}"
model_id = "kubiya/claude-sonnet-4"
runtime = data.controlplane_team.devops.runtime
team_id = data.controlplane_team.devops.id
llm_config = jsonencode({
temperature = 0.7
max_tokens = 4096
})
}
output "team_runtime" {
value = data.controlplane_team.devops.runtime
}
Exported Attributes:
id - Team ID
name - Team name
description - Team description
runtime - Runtime type (default or claude_code)
configuration - Team configuration (JSON)
capabilities - List of capabilities
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_agent
Look up an existing agent:
data "controlplane_agent" "existing" {
id = "agent-xxxxx"
}
# Clone agent configuration
resource "controlplane_agent" "clone" {
name = "cloned-agent"
description = "Clone of ${data.controlplane_agent.existing.name}"
model_id = data.controlplane_agent.existing.model_id
runtime = data.controlplane_agent.existing.runtime
llm_config = data.controlplane_agent.existing.llm_config
# Modify some settings
configuration = jsonencode({
environment = "staging"
})
}
output "agent_model" {
value = data.controlplane_agent.existing.model_id
}
output "agent_capabilities" {
value = data.controlplane_agent.existing.capabilities
}
Exported Attributes:
id - Agent ID
name - Agent name
description - Agent description
model_id - LLM model
runtime - Runtime type
team_id - Team ID
llm_config - LLM configuration (JSON)
configuration - Agent configuration (JSON)
capabilities - List of capabilities
status - Agent status
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_skill
Look up an existing skill:
data "controlplane_skill" "shell" {
id = "skill-xxxxx"
}
output "skill_type" {
value = data.controlplane_skill.shell.type
}
output "skill_config" {
value = data.controlplane_skill.shell.configuration
}
# Reference in documentation
locals {
available_commands = jsondecode(data.controlplane_skill.shell.configuration).allowed_commands
}
output "available_commands" {
value = local.available_commands
}
Exported Attributes:
id - Skill ID
name - Skill name
description - Skill description
type - Skill type (shell, file_system, docker, custom)
enabled - Whether skill is enabled
configuration - Skill configuration (JSON)
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_policy
Look up an existing policy:
data "controlplane_policy" "security" {
id = "policy-xxxxx"
}
output "policy_content" {
value = data.controlplane_policy.security.policy_content
sensitive = true
}
output "policy_tags" {
value = data.controlplane_policy.security.tags
}
# Reference policy in agent configuration
resource "controlplane_agent" "compliant_agent" {
name = "compliant-agent"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
configuration = jsonencode({
policies = [data.controlplane_policy.security.id]
})
}
Exported Attributes:
id - Policy ID
name - Policy name
description - Policy description
enabled - Whether policy is enabled
policy_content - OPA Rego policy content
tags - List of tags
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_job
Look up an existing job:
data "controlplane_job" "daily_backup" {
id = "job-xxxxx"
}
output "job_info" {
value = {
name = data.controlplane_job.daily_backup.name
trigger_type = data.controlplane_job.daily_backup.trigger_type
cron_schedule = data.controlplane_job.daily_backup.cron_schedule
enabled = data.controlplane_job.daily_backup.enabled
}
}
# Reference webhook URL
output "webhook_url" {
value = data.controlplane_job.daily_backup.webhook_url
sensitive = true
}
Exported Attributes:
id - Job ID
name - Job name
description - Job description
enabled - Whether job is enabled
status - Job status
trigger_type - Trigger type (cron, webhook, manual)
cron_schedule - Cron expression
cron_timezone - Timezone for cron schedule
webhook_url - Full webhook URL (for webhook triggers)
planning_mode - Planning mode
entity_type - Entity type (agent, team, workflow)
entity_id - Entity ID
prompt_template - Prompt template
system_prompt - System prompt
executor_type - Executor routing type
worker_queue_name - Worker queue name
environment_name - Environment name
created_at - Creation timestamp
updated_at - Last update timestamp
controlplane_jobs
List all jobs in the control plane:
data "controlplane_jobs" "all" {}
output "all_job_names" {
value = [for job in data.controlplane_jobs.all.jobs : job.name]
}
# Filter enabled cron jobs
locals {
cron_jobs = [
for job in data.controlplane_jobs.all.jobs : job
if job.trigger_type == "cron" && job.enabled
]
}
output "cron_jobs" {
value = local.cron_jobs
}
# Create agents based on existing jobs
resource "controlplane_agent" "job_monitors" {
for_each = {
for job in data.controlplane_jobs.all.jobs : job.id => job
if job.enabled
}
name = "monitor-${each.value.name}"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
llm_config = jsonencode({
temperature = 0.7
max_tokens = 4096
})
configuration = jsonencode({
monitored_job_id = each.value.id
})
}
Exported Attributes:
jobs - List of all jobs, each with the same attributes as controlplane_job data source
controlplane_worker_queue
Look up an existing worker queue:
data "controlplane_worker_queue" "primary" {
id = "queue-xxxxx"
}
output "queue_info" {
value = {
name = data.controlplane_worker_queue.primary.name
status = data.controlplane_worker_queue.primary.status
active_workers = data.controlplane_worker_queue.primary.active_workers
max_workers = data.controlplane_worker_queue.primary.max_workers
}
}
# Use in job configuration
resource "controlplane_job" "queue_specific" {
name = "queue-specific-job"
trigger_type = "manual"
planning_mode = "predefined_agent"
entity_type = "agent"
entity_id = var.agent_id
prompt_template = "Process task"
executor_type = "specific_queue"
worker_queue_name = data.controlplane_worker_queue.primary.name
}
Exported Attributes:
id - Worker Queue ID
environment_id - Environment ID
name - Worker queue name
display_name - Display name
description - Queue description
status - Worker queue status
max_workers - Maximum workers allowed
heartbeat_interval - Seconds between heartbeats
tags - List of tags
settings - Additional settings as map
created_at - Creation timestamp
updated_at - Last update timestamp
active_workers - Number of active workers
task_queue_name - Task queue name for Temporal
controlplane_worker_queues
List all worker queues in an environment:
data "controlplane_worker_queues" "production" {
environment_id = var.production_environment_id
}
output "production_queues" {
value = [
for queue in data.controlplane_worker_queues.production.queues : {
name = queue.name
active_workers = queue.active_workers
max_workers = queue.max_workers
status = queue.status
}
]
}
# Find queue with most capacity
locals {
available_queues = [
for queue in data.controlplane_worker_queues.production.queues : queue
if queue.status == "active" && (queue.max_workers == null || queue.active_workers < queue.max_workers)
]
best_queue = length(local.available_queues) > 0 ? local.available_queues[0] : null
}
# Create job on queue with capacity
resource "controlplane_job" "dynamic_routing" {
count = local.best_queue != null ? 1 : 0
name = "dynamic-job"
trigger_type = "manual"
planning_mode = "predefined_agent"
entity_type = "agent"
entity_id = var.agent_id
prompt_template = "Process on available queue"
executor_type = "specific_queue"
worker_queue_name = local.best_queue.name
}
Exported Attributes:
environment_id - Environment ID (input)
queues - List of worker queues, each with the same attributes as controlplane_worker_queue data source
Common Use Cases
Use Case 1: Cross-Stack References
Reference resources from a different Terraform state:
# In stack-a: Create base infrastructure
resource "controlplane_environment" "shared" {
name = "shared-environment"
}
output "shared_env_id" {
value = controlplane_environment.shared.id
}
# In stack-b: Reference base infrastructure
data "controlplane_environment" "shared" {
id = var.shared_environment_id # From stack-a output
}
resource "controlplane_agent" "app_agent" {
name = "app-agent"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
configuration = jsonencode({
environment = data.controlplane_environment.shared.name
})
}
Use Case 2: Dynamic Agent Creation
Create agents based on existing team configuration:
# Look up all teams
data "controlplane_team" "devops" {
id = var.devops_team_id
}
data "controlplane_team" "security" {
id = var.security_team_id
}
# Create agents for each team
locals {
teams = {
devops = data.controlplane_team.devops
security = data.controlplane_team.security
}
}
resource "controlplane_agent" "team_agents" {
for_each = local.teams
name = "${each.key}-agent"
model_id = "kubiya/claude-sonnet-4"
runtime = each.value.runtime
team_id = each.value.id
llm_config = jsonencode({
temperature = 0.7
max_tokens = 4096
})
}
Use Case 3: Configuration Validation
Validate that resources exist before creating dependencies:
# Verify environment exists
data "controlplane_environment" "required" {
id = var.environment_id
}
# Create resources only if environment exists
resource "controlplane_agent" "validated" {
count = data.controlplane_environment.required.id != "" ? 1 : 0
name = "validated-agent"
model_id = "kubiya/claude-sonnet-4"
runtime = "claude_code"
configuration = jsonencode({
environment = data.controlplane_environment.required.name
})
}
Use Case 4: Import Existing Resources
Find existing resources to import into Terraform:
# Look up existing agent
data "controlplane_agent" "existing" {
id = "agent-xxxxx"
}
# Verify it's the right agent
output "verify_agent" {
value = {
name = data.controlplane_agent.existing.name
model = data.controlplane_agent.existing.model_id
runtime = data.controlplane_agent.existing.runtime
}
}
# After verification, import it
# terraform import controlplane_agent.managed agent-xxxxx
# Then manage it with Terraform
resource "controlplane_agent" "managed" {
name = data.controlplane_agent.existing.name
model_id = data.controlplane_agent.existing.model_id
runtime = data.controlplane_agent.existing.runtime
# ... rest of configuration
}
Use Case 5: Clone Configurations
Clone existing resources with modifications:
# Look up production agent
data "controlplane_agent" "production" {
id = var.production_agent_id
}
# Create staging clone with same config
resource "controlplane_agent" "staging" {
name = "staging-${data.controlplane_agent.production.name}"
description = "Staging clone of production agent"
model_id = data.controlplane_agent.production.model_id
runtime = data.controlplane_agent.production.runtime
llm_config = data.controlplane_agent.production.llm_config
# Override environment-specific settings
configuration = jsonencode(
merge(
jsondecode(data.controlplane_agent.production.configuration),
{
environment = "staging"
timeout = 300 # Shorter timeout for staging
}
)
)
}
Working with JSON Attributes
Many data source attributes return JSON strings. Use jsondecode() to parse them:
data "controlplane_environment" "prod" {
id = "env-xxxxx"
}
locals {
env_config = jsondecode(data.controlplane_environment.prod.configuration)
max_workers = local.env_config.max_workers
region = local.env_config.region
}
output "environment_details" {
value = {
max_workers = local.max_workers
region = local.region
}
}
Best Practices
1. Use Variables for IDs
Don’t hardcode resource IDs:
# Good
variable "production_env_id" {
description = "Production environment ID"
type = string
}
data "controlplane_environment" "prod" {
id = var.production_env_id
}
# Avoid
data "controlplane_environment" "prod" {
id = "env-12345" # Hardcoded
}
2. Validate Data Source Results
Check that required data exists:
data "controlplane_team" "required" {
id = var.team_id
}
# Fail if team doesn't exist
resource "null_resource" "validate_team" {
triggers = {
team_exists = data.controlplane_team.required.id
}
lifecycle {
precondition {
condition = data.controlplane_team.required.id != ""
error_message = "Required team does not exist"
}
}
}
3. Document Data Source Usage
Add clear comments:
# Look up existing production environment
# Created manually or by base infrastructure stack
data "controlplane_environment" "production" {
id = var.production_env_id
}
4. Use Outputs for Debugging
Output data source attributes for troubleshooting:
output "debug_environment" {
value = {
id = data.controlplane_environment.prod.id
name = data.controlplane_environment.prod.name
config = data.controlplane_environment.prod.configuration
}
}
Error Handling
If a data source can’t find a resource:
Error: Cannot find resource with ID: agent-xxxxx
Solutions:
- Verify the resource ID is correct
- Check that the resource exists in your control plane
- Verify your API key has read permissions
- Ensure you’re connected to the correct control plane (hosted vs self-hosted)
Next Steps