Unlike unpredictable agent-based systems, Kubiya workflows are deterministic by design . Same input → Same execution path → Same output, every time.
The Problem with Non-Deterministic Systems
Traditional Agent Systems
Problems:
🎲 Different execution paths each time
🐛 Impossible to debug failures
📈 Errors compound through the chain
⏱️ Unpredictable execution time
🔍 No clear audit trail
Kubiya’s Deterministic Approach
Benefits:
✅ Same execution path every time
✅ Clear debugging with step-by-step logs
✅ Isolated failures don’t cascade
✅ Predictable performance
✅ Complete audit trail
What Makes Kubiya Deterministic?
1. DAG-Based Execution
Workflows are Directed Acyclic Graphs (DAGs) :
workflow = (
Workflow( "deploy-app" )
.step( "validate" , "validate.sh" )
.step( "build" , "docker build -t app:latest ." , depends_on = [ "validate" ])
.step( "test" , "pytest tests/" , depends_on = [ "build" ])
.step( "deploy" , "kubectl apply -f k8s/" , depends_on = [ "test" ])
)
Why DAGs?
No circular dependencies
Clear execution order
Parallelizable where possible
Stateless between runs
2. Isolated Step Execution
Each step runs in an isolated container:
# Step execution
apiVersion : batch/v1
kind : Job
metadata :
name : workflow-${id}-step-${name}
spec :
template :
spec :
containers :
- name : step
image : ${step.image}
command : ${step.command}
env : ${step.env}
restartPolicy : Never
Isolation Benefits:
No side effects between steps
Clean environment each time
Resource limits enforced
Security boundaries maintained
3. Immutable Workflow Definitions
Once defined, workflows don’t change during execution:
# Workflow is compiled to immutable JSON
{
"name" : "deploy-app" ,
"version" : "1.0.0" ,
"steps" : [
{
"name" : "validate" ,
"command" : "validate.sh" ,
"hash" : "abc123..." # Content-addressed
}
]
}
4. Explicit Dependencies
Dependencies are declared, not discovered:
# Clear dependency graph
.step( "fetch-data" , "wget data.csv" )
.step( "process" , "python process.py" , depends_on = [ "fetch-data" ])
.step( "upload" , "aws s3 cp output.csv s3://bucket/" , depends_on = [ "process" ])
Comparison with Other Systems
Feature Kubiya LangChain/Agents Traditional CI/CD Step Functions Deterministic ✅ Always ❌ Varies ✅ Yes ✅ Yes Debuggable ✅ Step-by-step ❌ Black box ⚠️ Limited ⚠️ Limited Scalable ✅ K8s native ❌ Single process ⚠️ Runner limits ✅ AWS only Portable ✅ Any K8s ❌ Python only ❌ Platform specific ❌ AWS only AI Integration ✅ Optional ✅ Core ❌ None ❌ None
Determinism in Practice
Example: Database Backup Workflow
backup_workflow = (
Workflow( "db-backup" )
# Always executes in this order
.step( "check-space" , "df -h /backup" )
.step( "dump-db" , "pg_dump -Fc mydb > backup.sql" , depends_on = [ "check-space" ])
.step( "compress" , "gzip backup.sql" , depends_on = [ "dump-db" ])
.step( "upload" , "aws s3 cp backup.sql.gz s3://backups/" , depends_on = [ "compress" ])
.step( "verify" , "aws s3 ls s3://backups/backup.sql.gz" , depends_on = [ "upload" ])
.step( "cleanup" , "rm backup.sql.gz" , depends_on = [ "verify" ])
)
Guarantees:
Space is always checked first
Database is only dumped if space available
Upload only happens after successful compression
Cleanup only after verification
Same execution order every time
Handling Non-Deterministic Operations
Even with external services, maintain determinism:
# Deterministic retry logic
.step( "api-call" ,
command = "curl https://api.example.com/data" ,
retry = RetryPolicy(
max_attempts = 3 ,
backoff = "exponential" ,
max_delay = 60
)
)
AI Integration Without Chaos
When using AI providers, the workflow structure remains deterministic:
# AI generates the workflow, but execution is deterministic
adk = get_provider( "adk" )
workflow = adk.generate_workflow( "backup databases" )
# The generated workflow is a fixed DAG
print (workflow)
# {
# "name": "backup-databases",
# "steps": [
# {"name": "check-disk", "command": "df -h"},
# {"name": "dump-postgres", "command": "pg_dump..."},
# ...
# ]
# }
# Execution is 100% predictable
client.execute_workflow(workflow)
Benefits for Production
1. Reliable Deployments
deploy_workflow = (
Workflow( "production-deploy" )
.step( "run-tests" , "pytest" )
.step( "build" , "docker build" , depends_on = [ "run-tests" ])
.step( "push" , "docker push" , depends_on = [ "build" ])
.step( "deploy" , "kubectl rollout" , depends_on = [ "push" ])
.step( "verify" , "curl health-check" , depends_on = [ "deploy" ])
)
# This ALWAYS follows the same path
# No surprises in production
2. Debugging Failures
# When something fails, you know exactly where
$ kubiya logs workflow-123
Step: run-tests [SUCCESS] 2.3s
Step: build [SUCCESS] 45.2s
Step: push [FAILED] 12.1s
Error: Registry timeout
Retry 1/3...
3. Compliance and Auditing
// Complete execution history
{
"workflow" : "financial-report" ,
"execution_id" : "exec-789" ,
"steps" : [
{
"name" : "fetch-transactions" ,
"started" : "2024-01-15T10:00:00Z" ,
"completed" : "2024-01-15T10:00:45Z" ,
"status" : "success" ,
"output_hash" : "sha256:abc..."
}
]
}
Best Practices for Deterministic Workflows
The Bottom Line
Predictable Same workflow, same execution, every time
Debuggable Clear visibility into every step
Auditable Complete execution history
Scalable Determinism enables parallelization
What’s Next?