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.0.tar.gz (31.8 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.0-py3-none-any.whl (26.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: foil_sdk-0.6.0.tar.gz
  • Upload date:
  • Size: 31.8 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.0.tar.gz
Algorithm Hash digest
SHA256 82e50d02ed12b7128f52546652dfb2b0d89b6d952fe6b41432602f6329ab8e0d
MD5 5473830f2e61aa165d1726a3498acca6
BLAKE2b-256 71ee27d4225fe12071d2f64c3ce5aad7e9be9c9e82261e0605c7f5959ee2d5f9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: foil_sdk-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 26.6 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7899bb68465a181851e1a7e67b789ca5fb50095672e922c42b6d1ce2e88632d1
MD5 5c8783ab6f8437327116dbf5cbd18eff
BLAKE2b-256 0466c7a68712fd499811d835dcd9d67d1f0caca4a486ef5ad5f13f486be0fe12

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