Integration Patterns
When integrating external services with Julep, following consistent patterns helps ensure security, reliability, and maintainability. This guide covers common integration patterns with a focus on using secrets effectively.
Authentication Patterns
API Key Authentication with Secrets
For services that use API keys for authentication, store them as secrets:
steps :
- kind : tool_call
tool : external_api
operation : fetch_data
arguments :
url : "https://api.example.com/data"
headers :
Authorization : "$ f'Bearer {secrets.api_key}'"
X-API-Key : "$ secrets.api_key"
OAuth Authentication with Secrets
For OAuth flows, keep client credentials in secrets:
steps :
- kind : tool_call
tool : oauth_service
operation : get_token
arguments :
client_id : "$ secrets.oauth_client_id"
client_secret : "$ secrets.oauth_client_secret"
scope : "read write"
output : token
- kind : tool_call
tool : api_service
operation : call_api
arguments :
url : "https://api.example.com/data"
headers :
Authorization : "Bearer {{ token }}"
Basic Authentication with Secrets
For services using basic authentication:
steps :
- kind : tool_call
tool : api_service
operation : call_api
arguments :
url : "https://api.example.com/data"
auth :
username : "$ secrets.api_username"
password : "$ secrets.api_password"
Integration Configuration Patterns
Database Connection with Secrets
When connecting to databases, use secrets for connection parameters:
steps :
- kind : tool_call
tool : database
operation : query
arguments :
query : "SELECT * FROM users LIMIT 10"
connection :
host : "$ secrets.db_host"
port : "$ secrets.db_port"
user : "$ secrets.db_username"
password : "$ secrets.db_password"
database : "$ secrets.db_name"
Service Configuration with Secrets
For configuring service endpoints and parameters:
steps :
- kind : tool_call
tool : email
operation : send
arguments :
to : "recipient@example.com"
subject : "Important update"
body : "This is an important message."
smtp :
host : "$ secrets.smtp_host"
port : "$ secrets.smtp_port"
username : "$ secrets.smtp_username"
password : "$ secrets.smtp_password"
tls : true
Advanced Integration Patterns
Hybrid Secret and Expression Pattern
Combine secrets with expressions for dynamic configurations:
steps :
- kind : transform
expression : "$ f'https://{secrets.api_domain}/v1/{input.resource}?api_key={secrets.api_key}'"
input :
resource : "users"
output : api_url
- kind : tool_call
tool : http
operation : get
arguments :
url : "{{ api_url }}"
Multi-tenant Service Integration
For handling multiple tenant configurations with secrets:
steps :
- kind : transform
expression : "$ f'tenant_{input.tenant_id}'"
input :
tenant_id : "123"
output : tenant_key
- kind : transform
expression : "$ f'{secrets[tenant_key + \" _api_key \" ]}'"
output : api_key
- kind : tool_call
tool : external_api
operation : fetch_data
arguments :
url : "https://api.example.com/data"
headers :
Authorization : "Bearer {{ api_key }}"
Service Discovery Pattern
For dynamically selecting services based on configuration:
steps :
- kind : transform
expression : "$ secrets.preferred_service"
output : service_name
- kind : if_else
if : "$ service_name == 'service_a'"
then :
- kind : tool_call
tool : service_a
operation : process
arguments :
input : "{{ input }}"
api_key : "$ secrets.service_a_api_key"
else :
- kind : tool_call
tool : service_b
operation : process
arguments :
data : "{{ input }}"
auth_token : "$ secrets.service_b_auth_token"
See all 21 lines
Best Practices
Secret Naming Conventions
Use descriptive names: stripe_api_key
instead of just api_key
Use service prefixes: aws_access_key
, aws_secret_key
For multiple environments: dev_api_key
, prod_api_key
Secret Rotation
Implement regular secret rotation without service disruption:
# Python example of rotating a secret
from julep import Julep
import uuid
client = Julep( api_key = "your_api_key" )
# Generate temporary name
temp_name = f "stripe_key_rotation_ { uuid.uuid4().hex[: 8 ] } "
# Create new secret with temp name
client.secrets.create(
name =temp_name,
value = "sk_new_value..." ,
description = "New Stripe API key (rotation)"
)
# Test the new key works
# ...
# If valid, delete old secret and rename new one
client.secrets.delete( name = "stripe_api_key" )
client.secrets.update(
name =temp_name,
new_name = "stripe_api_key" ,
description = "Stripe API key"
)
See all 26 lines
Error Handling
For graceful handling of authentication and configuration errors:
steps :
- kind : try_catch
try :
- kind : tool_call
tool : external_api
operation : fetch_data
arguments :
url : "https://api.example.com/data"
headers :
Authorization : "Bearer $ secrets.api_key"
catch :
- kind : if_else
if : "$ error.type == 'AuthenticationError'"
then :
- kind : prompt
model : gpt-4
prompt : "API key authentication failed. Please suggest troubleshooting steps."
else :
- kind : prompt
model : gpt-4
prompt : "An error occurred: {{ error.message }}"
See all 21 lines
Next Steps