Building AI Agents with Bash: An Unexpectedly Well-Functioning Example
While most developers reach for Python, JavaScript, or Go when building AI agents, there's something uniquely appealing about using bash.
Today, I'll show you how to build AI agents using nothing but bash, curl, and jq. This approach demonstrates that at its core, AI agent development is fundamentally about HTTP communication and JSON processing.
Disclaimer: This post is mostly in jest and meant to be humorous. Building AI agents with bash is a terrible idea for any serious application. While the approach described here technically works, it's not recommended for production use or any real-world scenarios. Please use our other SDKs for actual AI agent development.
The Core Components
To build an AI agent in bash, we need just three things:
bash
(version 4.0 or later)curl
for making HTTP requestsjq
for JSON processing
Setting Up Your Environment
First, let's set up our environment variables:
export INFERABLE_API_SECRET="your-api-secret"
export INFERABLE_API_ENDPOINT="https://api.inferable.ai"
Creating the Agent Handler
The heart of our AI agent is the handler script. This is where we define what our agent can do:
#!/bin/bash
function_name=$1
input=$2
case "$function_name" in
"greet")
name=$(echo "$input" | jq -r '.name')
echo "{\"message\": \"Hello, $name!\"}"
;;
"calculate")
numbers=$(echo "$input" | jq -r '.numbers[]')
sum=0
for num in $numbers; do
sum=$((sum + num))
done
echo "{\"result\": $sum}"
;;
*)
echo "{\"error\": \"Unknown function\"}"
;;
esac
The Main Service Loop
Here's where the magic happens. We need to:
- Register our service with Inferable
- Poll for new jobs
- Execute the requested functions
- Return results
# Define our functions
FUNCTIONS='[
{
"name": "greet",
"description": "Greet a user",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
}
}
]'
# Register the service
CLUSTER_ID=$(register_service "greeting-service" "$FUNCTIONS")
# Start polling with our handler
start_service "$CLUSTER_ID" "greeting-service" "./handler.sh"
Making It Production-Ready
To make this more robust, we should add:
- Error handling
- Retry logic
- Logging
- Health checks
Here's how we can enhance our service:
#!/bin/bash
# Add logging
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> service.log
}
# Add health checks
health_check() {
local response=$(make_request "GET" "/live")
if ! echo "$response" | jq -e '.status == "ok"' > /dev/null; then
log "Health check failed"
return 1
fi
return 0
}
# Add retry logic
with_retry() {
local max_attempts=3
local attempt=1
while [ $attempt -le $max_attempts ]; do
if "$@"; then
return 0
fi
log "Attempt $attempt failed, retrying..."
attempt=$((attempt + 1))
sleep $((attempt * 2))
done
return 1
}
The Power of Minimalism
While this bash-based approach might seem primitive, there are a few things I like about it:
- HTTP is Universal: At its core, AI agent development is about HTTP communication
- JSON is Simple: With
jq
, complex JSON operations become manageable
Limitations and Considerations
Of course, this approach has its limitations:
- Error Handling: Bash's error handling is relatively basic
- Async Operations: Bash isn't great at handling concurrent operations
- Type Safety: There's no built-in type checking
- Debugging: Debugging bash scripts can be challenging
When to Use This Approach
Never. Please don't. Nothing is as permanent as a temporary solution that works.
Conclusion
Building AI agents in bash is a fascinating exercise in minimalism and, quite frankly, a terrible idea for any serious application. While you definitely shouldn't use this approach in production (seriously, don't), it's a great way to understand the primitives behind AI agent development with Inferable (and learn some bash along the way). Sometimes, stripping away the complexity (and common sense) helps us see the core principles more clearly, even if it's through the lens of absurdity.
Ready to try this ridiculous experiment yourself? Check out the complete example implementation on GitHub.