Skip to main content

Foil SDK for monitoring and logging AI model invocations

Project description

Foil Python SDK

Python SDK for monitoring and logging AI agent invocations with Foil. Features distributed tracing, semantic search, multimodal content support (images, documents), signals/feedback, and OpenAI integration.

Installation

pip install foil-sdk

Or install from source:

pip install -e /path/to/foil-sdk

Quick Start

from foil import Foil, create_foil_tracer, SpanKind

# Create a tracer for your agent
tracer = create_foil_tracer(
    api_key="your-api-key",
    agent_name="my-agent",
    base_url="https://api.getfoil.ai/api",  # or your self-hosted URL
)

# Trace an agent execution
async def my_agent():
    async with tracer.trace("weather-query", input="User asked about weather") as ctx:
        # Create an LLM span
        span = await ctx.start_span(SpanKind.LLM, "gpt-4", input="What is the weather?")

        # ... call your LLM ...

        await span.end(
            output="The weather is sunny today!",
            tokens={"prompt": 10, "completion": 8, "total": 18}
        )

        return "Agent completed"

Table of Contents

Distributed Tracing

Using the Tracer

from foil import create_foil_tracer, SpanKind

tracer = create_foil_tracer(
    api_key="your-api-key",
    agent_name="customer-support-agent",
)

async with tracer.trace("support-query", input=user_message, session_id=conversation_id) as ctx:
    # LLM span for the main model call
    span = await ctx.start_span(SpanKind.LLM, "gpt-4-turbo", input=messages)

    response = await openai.chat.completions.create(
        model="gpt-4-turbo",
        messages=messages,
    )

    await span.end(
        output=response.choices[0].message.content,
        tokens={
            "prompt": response.usage.prompt_tokens,
            "completion": response.usage.completion_tokens,
            "total": response.usage.total_tokens,
        }
    )

Span Kinds

from foil import SpanKind

SpanKind.AGENT      # Root agent span
SpanKind.LLM        # Language model calls
SpanKind.TOOL       # Tool/function executions
SpanKind.CHAIN      # Chain of operations
SpanKind.RETRIEVER  # RAG retrieval operations
SpanKind.EMBEDDING  # Embedding model calls
SpanKind.CUSTOM     # Custom operation types

Nested Spans

async with tracer.trace("order-lookup") as ctx:
    # LLM decides to use a tool
    llm_span = await ctx.start_span(SpanKind.LLM, "gpt-4", input="Find order #12345")

    # Tool execution (child of LLM span)
    tool_span = await ctx.start_span(SpanKind.TOOL, "lookup_order", input={"order_id": "12345"})
    result = await database.find_order("12345")
    await tool_span.end(output=result)

    await llm_span.end(output=f"Order found: {result}")

Semantic Search

Search through your traces using natural language queries. Foil automatically embeds your trace content and enables AI-powered semantic search.

Basic Search

from foil import Foil

foil = Foil(
    api_key="your-api-key",
    base_url="https://api.getfoil.ai/api",
)

# Search for conversations about a topic
results = foil.semantic_search("conversations about refund requests")

print(f"Found {len(results['results'])} matching traces")
for result in results["results"]:
    print(f"Trace: {result['traceId']}, Similarity: {result['similarity'] * 100:.1f}%")

Search with Filters

results = foil.semantic_search(
    "user asking about pricing",
    agent_id="customer-support-agent",  # Filter by specific agent
    agent_name="support-bot",           # Or filter by agent name
    from_date="2024-01-01",             # Start date (ISO format)
    to_date="2024-12-31",               # End date (ISO format)
    limit=10,                           # Max results (default: 20)
    offset=0,                           # Pagination offset
    threshold=0.4,                      # Min similarity score 0-1 (default: 0.3)
)

Find Similar Traces

Find traces that are semantically similar to a specific trace:

# Find traces similar to a known trace
similar = foil.find_similar_traces(
    "trace-abc-123",
    limit=5,
    threshold=0.4,
)

print(f"Found {len(similar['results'])} similar traces")
for result in similar["results"]:
    print(f"{result['traceId']}: {result['similarity'] * 100:.1f}% similar")

Check Semantic Search Status

# Get overall embedding status
status = foil.get_semantic_search_status()
print(f"Embedded: {status['embeddedSpans']} / {status['totalSpans']} spans")
print(f"Coverage: {status['coveragePercent']}%")
print(f"Ready: {status['ready']}")

# Get status for specific agent
agent_status = foil.get_semantic_search_status("my-agent-id")

Multimodal Content

Foil supports multimodal input/output including images, documents, and other media types.

Media Categories

from foil import MediaCategory

MediaCategory.IMAGE       # Images (png, jpg, gif, webp, etc.)
MediaCategory.DOCUMENT    # Documents (pdf, doc, docx, etc.)
MediaCategory.SPREADSHEET # Spreadsheets (xlsx, csv, etc.)
MediaCategory.CODE        # Code files
MediaCategory.AUDIO       # Audio files
MediaCategory.VIDEO       # Video files
MediaCategory.ARCHIVE     # Archives (zip, tar, etc.)
MediaCategory.NOTEBOOK    # Jupyter notebooks
MediaCategory.OTHER       # Other file types

Uploading Media

from foil import Foil

foil = Foil(
    api_key="your-api-key",
    base_url="https://api.getfoil.ai/api",
)

# Upload from file path
result = foil.upload_media("/path/to/image.png")
print(result["mediaId"])   # 'media_abc123'
print(result["category"])  # 'image'
print(result["filename"])  # 'image.png'
print(result["mimeType"])  # 'image/png'

# Upload from bytes
with open("/path/to/document.pdf", "rb") as f:
    content = f.read()
result = foil.upload_media(
    content,
    filename="document.pdf",
    mime_type="application/pdf",
)

# Upload with trace/span association
result = foil.upload_media(
    "/path/to/image.png",
    trace_id="trace_123",
    span_id="span_456",
    direction="input",  # or "output"
)

Content Blocks

Use content blocks to create multimodal input/output:

from foil import content, ContentBlock, MediaCategory

# Create multimodal content array
multimodal_input = content(
    "Please analyze this image:",
    ContentBlock.media(
        upload_result["mediaId"],
        category=MediaCategory.IMAGE,
        filename="photo.jpg",
        mime_type="image/jpeg",
    ),
    "Focus on the composition and colors."
)

Media Retrieval

# Get media information
media_info = foil.get_media(media_id)

# Get presigned URL for download
url_info = foil.get_media_url(media_id, "original")
print(url_info["url"])  # Presigned S3 URL

# Get extracted content URL (for documents)
extracted_url = foil.get_media_url(media_id, "extracted")

# Batch get multiple media
batch_info = foil.batch_media_info([media_id1, media_id2, media_id3])

Signals & Feedback

Record user feedback and custom signals for your traces:

from foil import Foil

foil = Foil(api_key="your-api-key")

# Record a signal for a specific trace
foil.record_signal({
    "traceId": "trace_123",
    "signalName": "user_satisfaction",
    "value": 4,
    "signalType": "feedback",
    "source": "user",
})

# Batch record signals
foil.record_signal_batch([
    {"traceId": "trace_123", "signalName": "thumbs", "value": True, "source": "user"},
    {"traceId": "trace_123", "signalName": "rating", "value": 5, "source": "user"},
])

# Get signals for a trace
signals = foil.get_trace_signals("trace_123")

OpenAI Integration

Automatic logging for OpenAI calls:

from openai import OpenAI
from foil import Foil

foil = Foil(api_key="your-foil-api-key")
client = foil.wrap_openai(OpenAI())

# All chat completion calls are now automatically logged
response = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Hello!"}]
)

Supports both streaming and non-streaming responses.

Experiments (A/B Testing)

Get variant assignments for experiments:

from foil import Foil

foil = Foil(api_key="your-api-key")

# Get assigned variant for a user
assignment = foil.get_experiment_variant("experiment_123", user_id)

if assignment["inExperiment"]:
    print(assignment["variantName"])  # 'control' or 'treatment'
    print(assignment["config"])       # {'model': 'gpt-4', 'temperature': 0.7}

Low-Level API

For more control, use the Foil client directly:

from foil import Foil

foil = Foil(
    api_key="your-api-key",
    base_url="https://api.getfoil.ai/api",
)

# Manual span management
trace_id = foil.create_trace_id()
span_id = foil.create_span_id()

foil.start_span({
    "spanId": span_id,
    "traceId": trace_id,
    "name": "gpt-4",
    "agentName": "my-agent",
    "spanKind": "llm",
    "input": messages,
})

# ... do work ...

foil.end_span({
    "spanId": span_id,
    "traceId": trace_id,
    "agentName": "my-agent",
    "output": response,
    "tokens": {"prompt": 100, "completion": 50, "total": 150},
})

# Get trace data
trace = foil.get_trace(trace_id)

# List traces
traces = foil.list_traces(
    agent_name="my-agent",
    limit=10,
    from_date="2024-01-01T00:00:00Z",
)

API Reference

Foil Client

Initialization

foil = Foil(api_key="your-api-key", base_url="https://api.getfoil.ai/api")
Parameter Type Required Description
api_key str Yes Your Foil API key
base_url str No API base URL (default: https://api.getfoil.ai/api)

Semantic Search Methods

Method Description
semantic_search(query, **options) Search spans using natural language
find_similar_traces(trace_id, **options) Find traces similar to a given trace
get_semantic_search_status(agent_id=None) Get embedding statistics

Media Methods

Method Description
upload_media(file, **options) Upload media for multimodal content
get_media(media_id, content=None) Get media information
get_media_url(media_id, content="original") Get presigned download URL
batch_media_info(media_ids) Get info for multiple media

Signal Methods

Method Description
record_signal(data) Record a signal
record_signal_batch(signals) Record multiple signals
get_trace_signals(trace_id) Get signals for a trace

Trace Methods

Method Description
start_span(data) Start a span
end_span(data) End a span
get_trace(trace_id) Get trace with all spans
list_traces(**options) List traces with filters

Experiment Methods

Method Description
get_experiment_variant(experiment_id, identifier) Get variant assignment

Legacy Methods (Deprecated)

Method Replacement
start_invocation(data) Use start_span(data)
end_invocation(data) Use end_span(data)

Examples

See the examples/ directory for complete working examples:

  • semantic_search_example.py - Semantic search usage

Run examples:

export FOIL_API_KEY=your-api-key
export FOIL_BASE_URL=https://api.getfoil.ai/api
export FOIL_AGENT_ID=your-agent-id

python examples/semantic_search_example.py

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

foil_sdk-0.6.3.tar.gz (33.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

foil_sdk-0.6.3-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file foil_sdk-0.6.3.tar.gz.

File metadata

  • Download URL: foil_sdk-0.6.3.tar.gz
  • Upload date:
  • Size: 33.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for foil_sdk-0.6.3.tar.gz
Algorithm Hash digest
SHA256 6a3d61f268c346c9c3a75383343e612d621d79476bf4def0c6f7267fc6902938
MD5 caed492eac8ffa0c7a801fa926599857
BLAKE2b-256 eeab82d35d09c2290cce511ec981a499897781b579ace6ae8a804ef0fc2c4c82

See more details on using hashes here.

File details

Details for the file foil_sdk-0.6.3-py3-none-any.whl.

File metadata

  • Download URL: foil_sdk-0.6.3-py3-none-any.whl
  • Upload date:
  • Size: 27.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for foil_sdk-0.6.3-py3-none-any.whl
Algorithm Hash digest
SHA256 239aedce1e327df9ad3ac71af14492194c3c9f05b9f5618ff11aa82046575555
MD5 8afb5f7d9092b995626a78e410e1e552
BLAKE2b-256 1c32eb5ac808bf407334dc5ab45e33669d77778c7ed5c04c8241ec55eb4970b4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page