CLI Recipes¶
Bash recipes for common EpsimoAI API tasks. All examples use curl and jq. Requires a valid JWT — see Authentication for how to obtain one.
Prerequisites¶
# Install jq if not already available
# Ubuntu/Debian: sudo apt install jq
# macOS: brew install jq
# Base URL (set once)
export EPSIMO_URL="https://backend.epsimoagents.com"
Login and Save JWT¶
#!/bin/bash
# Login and persist the JWT for subsequent scripts
read -p "Email: " EMAIL
read -s -p "Password: " PASSWORD
echo
JWT=$(curl -s -X POST "$EPSIMO_URL/auth/login" \
-H "Content-Type: application/json" \
-d "{\"email\":\"$EMAIL\",\"password\":\"$PASSWORD\"}" \
| jq -r .jwt_token)
if [ "$JWT" = "null" ] || [ -z "$JWT" ]; then
echo "ERROR: Login failed. Check credentials."
exit 1
fi
echo "$JWT" > ~/.epsimo-jwt
chmod 600 ~/.epsimo-jwt
echo "JWT saved to ~/.epsimo-jwt (expires in 30 days)"
Helper: Load JWT in Scripts¶
# Add to the top of any script
JWT=$(cat ~/.epsimo-jwt 2>/dev/null)
if [ -z "$JWT" ]; then
echo "Not logged in. Run the login script first."
exit 1
fi
List Projects¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
echo "Your projects:"
curl -s "$EPSIMO_URL/projects/" \
-H "Authorization: Bearer $JWT" \
| jq -r '.[] | "\(.project_id) \(.name)"'
Example output:
a1b2c3d4-... My Main Project
e5f6a7b8-... Client Demo
Switch Project¶
#!/bin/bash
# Switch to a specific project and save the project-scoped JWT
JWT=$(cat ~/.epsimo-jwt)
PROJECT_ID="$1"
if [ -z "$PROJECT_ID" ]; then
echo "Usage: $0 <project-id>"
echo "Run 'list-projects' to see available IDs."
exit 1
fi
PROJECT_JWT=$(curl -s "$EPSIMO_URL/projects/$PROJECT_ID" \
-H "Authorization: Bearer $JWT" \
| jq -r .jwt_token)
if [ "$PROJECT_JWT" = "null" ] || [ -z "$PROJECT_JWT" ]; then
echo "ERROR: Could not switch to project $PROJECT_ID"
exit 1
fi
echo "$PROJECT_JWT" > ~/.epsimo-jwt
echo "Switched to project $PROJECT_ID. JWT updated."
List Threads¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
curl -s "$EPSIMO_URL/threads" \
-H "Authorization: Bearer $JWT" \
| jq -r '.[] | "\(.thread_id) \(.name // "unnamed") \(.updated_at)"'
Create a Thread¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
THREAD_NAME="${1:-New Thread}"
RESPONSE=$(curl -s -X POST "$EPSIMO_URL/threads" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{\"name\":\"$THREAD_NAME\"}")
THREAD_ID=$(echo "$RESPONSE" | jq -r .thread_id)
echo "Created thread: $THREAD_ID"
echo "$THREAD_ID"
Send a Message and Stream the Response¶
#!/bin/bash
# Usage: ./send-message.sh <assistant-id> <thread-id> "Your message"
JWT=$(cat ~/.epsimo-jwt)
ASSISTANT_ID="$1"
THREAD_ID="$2"
MESSAGE="$3"
if [ -z "$ASSISTANT_ID" ] || [ -z "$THREAD_ID" ] || [ -z "$MESSAGE" ]; then
echo "Usage: $0 <assistant-id> <thread-id> \"message\""
exit 1
fi
# Stream the response and parse SSE events
curl -s -N "$EPSIMO_URL/runs/stream" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{
\"assistant_id\": \"$ASSISTANT_ID\",
\"thread_id\": \"$THREAD_ID\",
\"input\": [{\"role\": \"human\", \"content\": \"$MESSAGE\"}]
}" | while IFS= read -r line; do
# Skip empty lines and event type lines
if [[ "$line" == data:* ]]; then
DATA="${line#data: }"
# Extract content from messages/partial events
CONTENT=$(echo "$DATA" | jq -r '
if type == "array" then
.[-1].content // empty
elif .content? then
.content
else
empty
end
' 2>/dev/null)
if [ -n "$CONTENT" ]; then
printf "\r%s" "$CONTENT"
fi
fi
done
echo ""
Simpler Version (Collect Full Response)¶
#!/bin/bash
# Collects the full response without real-time streaming display
JWT=$(cat ~/.epsimo-jwt)
ASSISTANT_ID="$1"
THREAD_ID="$2"
MESSAGE="$3"
RESPONSE=$(curl -s -N "$EPSIMO_URL/runs/stream" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{
\"assistant_id\": \"$ASSISTANT_ID\",
\"thread_id\": \"$THREAD_ID\",
\"input\": [{\"role\": \"human\", \"content\": \"$MESSAGE\"}]
}" | grep "^data:" | tail -2 | head -1 | sed 's/^data: //')
echo "$RESPONSE" | jq -r '.[-1].content // .content // .'
List Assistants¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
echo "Assistants in current project:"
curl -s "$EPSIMO_URL/assistants" \
-H "Authorization: Bearer $JWT" \
| jq -r '.[] | "\(.assistant_id) \(.name) [access: \(.config.configurable["type==agent/access_mode"] // "authenticated")]"'
Create an Assistant¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
NAME="${1:-My New Assistant}"
SYSTEM_PROMPT="${2:-You are a helpful assistant.}"
RESPONSE=$(curl -s -X POST "$EPSIMO_URL/assistants" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$NAME\",
\"config\": {
\"configurable\": {
\"type==agent/system_message\": \"$SYSTEM_PROMPT\",
\"type==agent/access_mode\": \"authenticated\"
}
}
}")
ASSISTANT_ID=$(echo "$RESPONSE" | jq -r .assistant_id)
echo "Created assistant: $ASSISTANT_ID ($NAME)"
Create a Public Assistant (with Token)¶
#!/bin/bash
JWT=$(cat ~/.epsimo-jwt)
NAME="${1:-Public Bot}"
TOKEN="pubkey_$(openssl rand -hex 16)"
RESPONSE=$(curl -s -X POST "$EPSIMO_URL/assistants" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$NAME\",
\"config\": {
\"configurable\": {
\"type==agent/system_message\": \"You are a helpful assistant.\",
\"type==agent/access_mode\": \"public_token\",
\"type==agent/public_token\": \"$TOKEN\"
}
}
}")
ASSISTANT_ID=$(echo "$RESPONSE" | jq -r .assistant_id)
echo "Created public assistant: $ASSISTANT_ID"
echo "Public token: $TOKEN"
echo ""
echo "Test it:"
echo " curl $EPSIMO_URL/public/openai/v1/chat/completions \\"
echo " -H 'Authorization: Bearer $TOKEN' \\"
echo " -H 'Content-Type: application/json' \\"
echo " -d '{\"model\":\"gpt-4o\",\"messages\":[{\"role\":\"user\",\"content\":\"Hello\"}]}'"
Full Interactive Chat Session¶
#!/bin/bash
# Interactive chat loop with an assistant
JWT=$(cat ~/.epsimo-jwt)
ASSISTANT_ID="$1"
if [ -z "$ASSISTANT_ID" ]; then
echo "Usage: $0 <assistant-id>"
exit 1
fi
# Create a new thread for this session
THREAD_ID=$(curl -s -X POST "$EPSIMO_URL/threads" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"name":"CLI Chat Session"}' \
| jq -r .thread_id)
echo "Chat session started (thread: $THREAD_ID)"
echo "Type 'quit' to exit."
echo "---"
while true; do
read -p "You: " MESSAGE
[ "$MESSAGE" = "quit" ] && break
[ -z "$MESSAGE" ] && continue
printf "Assistant: "
curl -s -N "$EPSIMO_URL/runs/stream" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d "{
\"assistant_id\": \"$ASSISTANT_ID\",
\"thread_id\": \"$THREAD_ID\",
\"input\": [{\"role\": \"human\", \"content\": \"$MESSAGE\"}]
}" | grep "^data:" | while IFS= read -r line; do
DATA="${line#data: }"
CONTENT=$(echo "$DATA" | jq -r '
if type == "array" then .[-1].content // empty
else empty end
' 2>/dev/null)
[ -n "$CONTENT" ] && printf "\r%s" "$CONTENT"
done
echo ""
done
echo "Session ended."
Related Documentation¶
- Authentication Guide — All auth mechanisms and token details
- API Reference — Full endpoint documentation with Swagger/ReDoc links
- Public Assistants — Exposing assistants publicly
- OpenAI-Compatible Endpoint — Using OpenAI SDKs with EpsimoAI