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:

  1. bash (version 4.0 or later)
  2. curl for making HTTP requests
  3. jq 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:

  1. Register our service with Inferable
  2. Poll for new jobs
  3. Execute the requested functions
  4. 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:

  1. Error handling
  2. Retry logic
  3. Logging
  4. 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:

  1. HTTP is Universal: At its core, AI agent development is about HTTP communication
  2. JSON is Simple: With jq, complex JSON operations become manageable

Limitations and Considerations

Of course, this approach has its limitations:

  1. Error Handling: Bash's error handling is relatively basic
  2. Async Operations: Bash isn't great at handling concurrent operations
  3. Type Safety: There's no built-in type checking
  4. 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.