> ## Documentation Index
> Fetch the complete documentation index at: https://docs.baytos.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Context Files and URLs

> Work with files and URLs attached to prompts

# Context Files and URLs

Prompts can have attached context items - files and URLs that provide additional information when using the prompt.

## Understanding Context

Context items are attachments that supplement a prompt:

* **Files** - Documents, images, data files uploaded to Claro
* **URLs** - Web pages or external resources

```python theme={null}
from baytos.claro import BaytClient

client = BaytClient(api_key="your_api_key")
prompt = client.get_prompt("@workspace/research-assistant:v1")

# Check if prompt has context
if prompt.has_context():
    print(f"This prompt has {len(prompt.context)} context items")
```

## Checking for Context

Before working with context, check if it exists:

```python theme={null}
prompt = client.get_prompt("@workspace/my-prompt:v1")

# Check if any context exists
if prompt.has_context():
    print("Prompt has attachments")

# Get all context items
context_items = prompt.context
for item in context_items:
    print(f"- {item.type}: {item}")
```

## File Contexts

### Getting File Contexts

```python theme={null}
prompt = client.get_prompt("@workspace/prompt-with-files:v1")

# Get only file-type contexts
files = prompt.get_file_contexts()

for file in files:
    print(f"File: {file.file_name}")
    print(f"Size: {file.file_size:,} bytes")
    print(f"Type: {file.mime_type}")
    print()
```

### File Metadata

Each file context provides:

```python theme={null}
file = files[0]

# Basic info
print(f"ID: {file.id}")
print(f"Type: {file.type}")  # Always "file"
print(f"Label: {file.label}")  # Optional custom label

# File-specific info
print(f"Filename: {file.file_name}")
print(f"Size: {file.file_size} bytes")
print(f"MIME type: {file.mime_type}")
print(f"Created: {file.created_at}")  # Unix timestamp
```

### Downloading Files

Download file content to memory:

```python theme={null}
prompt = client.get_prompt("@workspace/data-analysis:v1")
files = prompt.get_file_contexts()

if files:
    file = files[0]

    # Download file content
    content = client.download_context_file(file.id)

    # Content is returned as bytes
    print(f"Downloaded {len(content):,} bytes")

    # Save to disk
    with open(file.file_name, 'wb') as f:
        f.write(content)

    print(f"Saved to: {file.file_name}")
```

### Getting Download URLs

For large files or delegating downloads, get a signed URL:

```python theme={null}
file = files[0]

# Get signed download URL
url_info = client.get_context_download_url(file.id)

download_url = url_info['url']
expires_in = url_info['expiresIn']  # Seconds until expiry

print(f"Download URL: {download_url}")
print(f"Expires in: {expires_in} seconds")

# URL is pre-signed, no authentication needed
# Can be passed to browser, other services, etc.
```

<Note>
  Download URLs expire after 1 hour by default. Generate a new URL if needed.
</Note>

### Example: Download All Files

```python theme={null}
import os
from baytos.claro import BaytClient

client = BaytClient(api_key=os.getenv("BAYT_API_KEY"))
prompt = client.get_prompt("@workspace/research:v1")

# Create directory for downloads
os.makedirs("downloads", exist_ok=True)

# Download all files
files = prompt.get_file_contexts()
for file in files:
    print(f"Downloading {file.file_name}...")

    content = client.download_context_file(file.id)

    # Save with original filename
    filepath = os.path.join("downloads", file.file_name)
    with open(filepath, 'wb') as f:
        f.write(content)

    print(f"  Saved: {filepath} ({file.file_size:,} bytes)")

print(f"\nDownloaded {len(files)} file(s)")
```

## URL Contexts

### Getting URL Contexts

```python theme={null}
prompt = client.get_prompt("@workspace/web-research:v1")

# Get only URL-type contexts
urls = prompt.get_url_contexts()

for url_item in urls:
    print(f"URL: {url_item.url}")
    if url_item.label:
        print(f"Label: {url_item.label}")
    if url_item.url_fetched_at:
        print(f"Fetched: {url_item.url_fetched_at}")
    print()
```

### URL Metadata

Each URL context provides:

```python theme={null}
url_item = urls[0]

# Basic info
print(f"ID: {url_item.id}")
print(f"Type: {url_item.type}")  # Always "url"
print(f"Label: {url_item.label}")  # Optional custom label

# URL-specific info
print(f"URL: {url_item.url}")
print(f"Fetched at: {url_item.url_fetched_at}")  # Unix timestamp
```

## Working with Mixed Context

Handle both files and URLs:

```python theme={null}
prompt = client.get_prompt("@workspace/comprehensive:v1")

# Get all context items
for item in prompt.context:
    if item.is_file():
        print(f"📄 File: {item.file_name} ({item.file_size:,} bytes)")
    elif item.is_url():
        print(f"🔗 URL: {item.url}")
```

## Type Checking

Check context item types:

```python theme={null}
for item in prompt.context:
    # Method 1: Use helper methods
    if item.is_file():
        print(f"This is a file: {item.file_name}")

    if item.is_url():
        print(f"This is a URL: {item.url}")

    # Method 2: Check type property
    if item.type == "file":
        print("File type")
    elif item.type == "url":
        print("URL type")
```

## Complete Example

```python theme={null}
#!/usr/bin/env python3
"""
Example: Download all context files from a prompt
"""

import os
from pathlib import Path
from baytos.claro import BaytClient

def download_prompt_context(package_name: str, output_dir: str = "downloads"):
    """Download all files attached to a prompt"""

    client = BaytClient(api_key=os.getenv("BAYT_API_KEY"))
    prompt = client.get_prompt(package_name)

    print(f"Prompt: {prompt.title}")
    print(f"Package: {prompt.package_name}\n")

    if not prompt.has_context():
        print("No context items attached to this prompt")
        return

    # Create output directory
    Path(output_dir).mkdir(parents=True, exist_ok=True)

    # Process all context items
    files = prompt.get_file_contexts()
    urls = prompt.get_url_contexts()

    # Download files
    if files:
        print(f"Downloading {len(files)} file(s)...\n")
        for i, file in enumerate(files, 1):
            print(f"{i}. {file.file_name}")
            print(f"   Size: {file.file_size:,} bytes")
            print(f"   Type: {file.mime_type}")

            # Download
            content = client.download_context_file(file.id)

            # Save
            filepath = Path(output_dir) / file.file_name
            filepath.write_bytes(content)

            print(f"   Saved: {filepath}")
            print()

    # List URLs
    if urls:
        print(f"\n{len(urls)} URL(s):")
        for i, url_item in enumerate(urls, 1):
            label = url_item.label or "Untitled"
            print(f"{i}. {label}: {url_item.url}")

    print("\nDone!")

if __name__ == "__main__":
    download_prompt_context("@workspace/research-assistant:v1")
```

## Error Handling

Handle common errors when working with context:

```python theme={null}
from baytos.claro import (
    BaytClient,
    BaytNotFoundError,
    BaytAuthError,
    BaytValidationError
)

client = BaytClient(api_key="...")

try:
    prompt = client.get_prompt("@workspace/my-prompt:v1")
    files = prompt.get_file_contexts()

    if files:
        content = client.download_context_file(files[0].id)

except BaytNotFoundError:
    print("Prompt or file not found")
except BaytAuthError:
    print("Authentication failed - check your API key")
except BaytValidationError as e:
    print(f"Invalid request: {e}")
except Exception as e:
    print(f"Error: {e}")
```

## Best Practices

<AccordionGroup>
  <Accordion title="Check Context Existence" icon="shield-check">
    Always check if context exists before accessing:

    ```python theme={null}
    # ✅ Good: Check first
    if prompt.has_context():
        files = prompt.get_file_contexts()
        if files:
            content = client.download_context_file(files[0].id)

    # ❌ Bad: Assume context exists
    files = prompt.get_file_contexts()
    content = client.download_context_file(files[0].id)  # May fail!
    ```
  </Accordion>

  <Accordion title="Handle Large Files Carefully" icon="database">
    For large files, consider using download URLs instead of downloading to memory:

    ```python theme={null}
    MAX_MEMORY_SIZE = 50 * 1024 * 1024  # 50 MB

    for file in files:
        if file.file_size > MAX_MEMORY_SIZE:
            # Get URL instead of downloading
            url_info = client.get_context_download_url(file.id)
            print(f"Large file - use URL: {url_info['url']}")
        else:
            # Safe to download to memory
            content = client.download_context_file(file.id)
    ```
  </Accordion>

  <Accordion title="Sanitize Filenames" icon="shield">
    Sanitize filenames before saving to disk:

    ```python theme={null}
    import re
    from pathlib import Path

    def safe_filename(filename: str) -> str:
        """Remove unsafe characters from filename"""
        # Remove path traversal attempts
        filename = Path(filename).name
        # Remove unsafe characters
        filename = re.sub(r'[^\w\s.-]', '', filename)
        return filename

    for file in files:
        safe_name = safe_filename(file.file_name)
        content = client.download_context_file(file.id)

        with open(safe_name, 'wb') as f:
            f.write(content)
    ```
  </Accordion>

  <Accordion title="Process Files by Type" icon="filter">
    Filter and process files based on MIME type:

    ```python theme={null}
    files = prompt.get_file_contexts()

    # Process only images
    image_files = [f for f in files if f.mime_type.startswith('image/')]

    # Process only PDFs
    pdf_files = [f for f in files if f.mime_type == 'application/pdf']

    # Process text files
    text_files = [f for f in files if f.mime_type.startswith('text/')]

    for pdf in pdf_files:
        content = client.download_context_file(pdf.id)
        # Process PDF...
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Variables" icon="brackets-curly" href="/sdk/python/variables">
    Extract and validate variables in prompts
  </Card>

  <Card title="Error Handling" icon="shield" href="/sdk/python/error-handling">
    Handle errors gracefully
  </Card>

  <Card title="Advanced Features" icon="rocket" href="/sdk/python/advanced">
    Performance optimization and caching
  </Card>

  <Card title="API Reference" icon="book" href="/sdk/python/api-reference">
    Complete API documentation
  </Card>
</CardGroup>
