Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.julep.ai/llms.txt

Use this file to discover all available pages before exploring further.

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"

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"
)

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 }}"

Next Steps