> ## Documentation Index
> Fetch the complete documentation index at: https://notte-experiment-visibility-md-links.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Function Management

> Update, version, monitor, and manage your deployed Functions

Manage the lifecycle of your Functions including updates, versioning, monitoring executions, and viewing replays.

## Viewing Functions

### List All Functions

View all deployed Functions:

{/* @sniptest testers/functions/list_functions.py */}

```python list_functions.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# List all functions
functions = client.functions.list()

for func in functions.items:
    print(f"ID: {func.workflow_id}")
    print(f"Name: {func.name}")
    print(f"Version: {func.latest_version}")
    print(f"Created: {func.created_at}")
    print("---")
```

### Get Function Details

Retrieve specific Function information:

{/* @sniptest testers/functions/management/get_function_details.py */}

```python get_function_details.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Get function by ID
function = client.Function(function_id="func_abc123")

# Access function properties
print(f"Function ID: {function.function_id}")
print(f"Name: {function.response.name}")
print(f"Description: {function.response.description}")
print(f"Latest Version: {function.response.latest_version}")
print(f"Versions: {function.response.versions}")
```

## Updating Functions

### Update Function Code

Deploy a new version of your Function:

{/* @sniptest testers/functions/management/update_code.py */}

```python update_code.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Update with new code
function.update(path="updated_function.py")

print(f"Updated to version: {function.response.latest_version}")
```

### Update Function Metadata

Change Function name or description:

```python theme={null}
# Update metadata (via console or API)
# Name and description updates are available through the Console
```

**Note:** Function updates create new versions automatically. Previous versions remain accessible for rollback.

## Versioning

### Version Management

Functions automatically version on each update:

{/* @sniptest testers/functions/management/version_management.py */}

```python version_management.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Get all versions
print(f"Available versions: {function.response.versions}")

# Get latest version
print(f"Latest: {function.response.latest_version}")
```

### Run Specific Version

Execute a specific Function version:

{/* @sniptest testers/functions/management/run_specific_version.py */}

```python run_specific_version.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Run latest version (default)
result = function.run(url="https://example.com")

# Run specific version
result = function.run(url="https://example.com", version="v2")
```

### Version History

Track changes across versions:

{/* @sniptest testers/functions/management/version_history.py */}

```python version_history.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

functions = client.functions.list()

for func in functions.items:
    print(f"Function: {func.name}")
    print(f"Versions: {', '.join(func.versions)}")
    print(f"Latest: {func.latest_version}")
```

## Monitoring Executions

### View Run History

List recent Function executions:

{/* @sniptest testers/functions/management/view_run_history.py */}

```python view_run_history.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Get recent runs
runs = client.functions.list_runs(
    function_id="function_abc123",
    only_active=False,  # Include completed runs
)

for run in runs.items:
    print(f"Run ID: {run.workflow_run_id}")
    print(f"Status: {run.status}")
    print(f"Created: {run.created_at}")
    print(f"Updated: {run.updated_at}")
    print("---")
```

### Check Run Status

Monitor specific execution:

{/* @sniptest testers/functions/management/check_run_status.py */}

```python check_run_status.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Get run details
run_status = client.functions.get_run("function_abc123", "run_xyz789")

print(f"Status: {run_status.status}")  # "active", "closed", "failed"
print(f"Result: {run_status.result}")
print(f"Session ID: {run_status.session_id}")
```

**Status values:**

* `active` - Function is currently running
* `closed` - Function completed successfully
* `failed` - Function encountered an error

### Filter Active Runs

View only running executions:

{/* @sniptest testers/functions/management/filter_active_runs.py */}

```python filter_active_runs.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Get only active runs
active_runs = client.functions.list_runs("function_abc123", only_active=True)

print(f"Active runs: {len(active_runs.items)}")

for run in active_runs.items:
    print(f"Run {run.workflow_run_id} - {run.status}")
```

## Viewing Replays

### Access Function Replay

Watch MP4 replay of Function execution:

{/* @sniptest testers/functions/management/access_replay.py */}

```python access_replay.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Run the function first
result = function.run(url="https://example.com")

# Get replay for this run (uses the session from the last run)
replay = function.replay()

# Download the replay
replay.download("function_replay.mp4")
```

**Replay features:**

* Video recording of browser session
* Shows all actions taken
* Useful for debugging failures
* Available after running a function

### Replay After Run

Get replay immediately after execution:

{/* @sniptest testers/functions/management/replay_after_run.py */}

```python replay_after_run.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Run function
result = function.run(url="https://example.com")

# Get replay for this run (automatically uses the session from the run)
replay = function.replay()

# Download the video
replay.download("execution_replay.mp4")
```

## Managing Runs

### Stop Running Function

Cancel a long-running execution:

{/* @sniptest testers/functions/management/stop_running.py */}

```python stop_running.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Stop specific run
client.functions.stop_run("function_abc123", "run_xyz789")

print("Function execution stopped")
```

### Monitoring Long Runs

Track execution progress:

{/* @sniptest testers/functions/monitor_runs.py */}

```python monitor_runs.py theme={null}
import time

from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Start run
result = function.run(
    url="https://example.com",
    stream=False,  # Don't stream logs
)

run_id = result.workflow_run_id

# Poll status
while True:
    status = client.functions.get_run("func_abc123", run_id)

    print(f"Status: {status.status}")

    if status.status in ["closed", "failed"]:
        print(f"Final result: {status.result}")
        break

    time.sleep(5)  # Check every 5 seconds
```

## Forking Functions

### Fork Shared Function

Create your own copy of a shared Function:

{/* @sniptest testers/functions/management/fork_function.py */}

```python fork_function.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Fork a function from marketplace or teammate
original = client.Function(function_id="func_abc123")
forked_function = original.fork()

print(f"Forked function ID: {forked_function.function_id}")
print("Original ID: func_abc123")
```

**Use cases:**

* Customize shared Functions
* Create templates from marketplace
* Copy teammate's Functions
* Experiment without affecting original

### Modify Forked Function

After forking, update as needed:

{/* @sniptest testers/functions/management/modify_forked.py */}

```python modify_forked.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Fork function
original = client.Function(function_id="shared_function_id")
forked = original.fork()

# Update your copy
forked.update(path="my_modified_version.py")

# Run your version
result = forked.run(url="https://example.com")
```

## Downloading Functions

### Download Function Code

Retrieve Function source code:

{/* @sniptest testers/functions/management/download_code.py */}

```python download_code.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(
    function_id="func_abc123",
    decryption_key="your-decryption-key",  # Required for downloading
)

# Download function code
code = function.download()

print(code)  # Function source code

# Or download directly to a file
code = function.download(path="downloaded_function.py")
```

**Requirements:**

* Decryption key (available in Console) - passed when creating Function instance
* Only works for Functions you own or have access to

### Download for Backup

Back up all your Functions:

{/* @sniptest testers/functions/management/backup_functions.py */}

```python backup_functions.py theme={null}
import os

from notte_sdk import NotteClient

client = NotteClient()

functions = client.functions.list()

# Create backup directory
os.makedirs("function_backups", exist_ok=True)

for func in functions.items:
    function = client.Function(function_id=func.workflow_id, decryption_key="your-key")

    try:
        code = function.download()

        filename = f"function_backups/{func.name}_{func.latest_version}.py"
        with open(filename, "w") as f:
            f.write(code)

        print(f"Backed up: {func.name}")
    except Exception as e:
        print(f"Failed to backup {func.name}: {e}")
```

## Deleting Functions

### Delete Function

Remove a Function permanently:

{/* @sniptest testers/functions/management/delete_function.py */}

```python delete_function.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Delete function
function.delete()

print("Function deleted")
```

**Warning:**

* Deletion is permanent
* All versions are deleted
* Run history is preserved
* Cannot be undone

## Sharing Functions

### Make Function Public

Share Functions with others:

{/* @sniptest testers/functions/management/make_public.py */}

```python make_public.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

# Deploy as shared
function = client.Function(
    path="my_function.py",
    name="Public Scraper",
    shared=True,  # Make publicly accessible
)
```

**Shared Functions:**

* ✅ Others can view and fork
* ✅ Original remains under your control
* ❌ Others cannot modify your version
* ✅ Usage tracked to your account

### Private Functions

Keep Functions private (default):

{/* @sniptest testers/functions/management/private_function.py */}

```python private_function.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(
    path="my_function.py",
    name="Private Automation",
    shared=False,  # Private (default)
)
```

## Best Practices

### 1. Version Your Functions

Update incrementally with clear changes:

{/* @sniptest testers/functions/management/version_backup.py */}

```python version_backup.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

# Before major update, download current version
current_code = function.download(decryption_key="key")

# Save backup
with open(f"backups/function_v{function.response.latest_version}.py", "w") as f:
    f.write(current_code)

# Update function
function.update(path="new_version.py")
```

### 2. Monitor Function Health

Regular health checks:

{/* @sniptest testers/functions/function_health_check.py */}

```python function_health_check.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()


def check_function_health(function_id: str):
    """Check recent run success rate."""
    runs = client.functions.list_runs(function_id, only_active=False)

    total = len(runs.items)
    failed = sum(1 for r in runs.items if r.status == "failed")

    success_rate = ((total - failed) / total * 100) if total > 0 else 0

    print(f"Success rate: {success_rate:.1f}%")
    print(f"Total runs: {total}")
    print(f"Failed runs: {failed}")

    return success_rate


# Monitor function
check_function_health("func_abc123")
```

### 3. Clean Up Old Runs

Archive or analyze old execution data:

{/* @sniptest testers/functions/management/cleanup_old_runs.py */}

```python cleanup_old_runs.py theme={null}
import json
from datetime import datetime, timedelta

from notte_sdk import NotteClient

client = NotteClient()


def archive_old_runs(function_id: str, days_old: int = 30):
    """Archive runs older than specified days."""
    runs = client.functions.list_runs(function_id, only_active=False)

    cutoff_date = datetime.now() - timedelta(days=days_old)
    archive = []

    for run in runs.items:
        if run.created_at < cutoff_date:
            archive.append(
                {
                    "run_id": run.workflow_run_id,
                    "status": run.status,
                    "created_at": run.created_at.isoformat(),
                    "result": str(run.result)[:100],  # First 100 chars
                }
            )

    # Save archive
    with open(f"archives/{function_id}_{datetime.now().date()}.json", "w") as f:
        json.dump(archive, f, indent=2)

    print(f"Archived {len(archive)} old runs")


archive_old_runs("function_abc123")
```

### 4. Document Changes

Keep change log for Function updates:

{/* @sniptest testers/functions/management/document_changes.py */}

```python document_changes.py theme={null}
"""
Function: Data Scraper
Function ID: func_abc123

Version History:
- v1 (2024-01-15): Initial release
- v2 (2024-01-20): Added error handling
- v3 (2024-01-25): Improved scraping accuracy
- v4 (2024-02-01): Added retry logic
"""


def run(url: str):
    # Your function code
    pass
```

### 5. Test Before Production

Validate updates before deploying:

{/* @sniptest testers/functions/management/test_before_prod.py */}

```python test_before_prod.py theme={null}
from notte_sdk import NotteClient


def validate_before_production():
    client = NotteClient()

    # Test locally first - decryption key needed for local execution
    function = client.Function(function_id="func_abc123", decryption_key="your-key")

    # Run with local=True for testing
    test_result = function.run(url="https://test-site.com", local=True)

    if test_result.status == "closed":
        print("Test passed, ready to update production")
        function.update(path="tested_function.py")
    else:
        print(f"Test failed: {test_result.result}")
```

## Troubleshooting

### Function Fails to Run

Check run details for errors:

{/* @sniptest testers/functions/management/troubleshoot_fails.py */}

```python troubleshoot_fails.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

function = client.Function(function_id="func_abc123")

run = client.functions.get_run("func_abc123", "run_xyz789")

if run.status == "failed":
    print(f"Error: {run.result}")

    # Run the function to get a replay
    result = function.run()
    replay = function.replay()
    replay.download("debug_replay.mp4")
```

### Missing Environment Variables

Verify configuration:

{/* @sniptest testers/functions/management/missing_env_vars.py */}

```python missing_env_vars.py theme={null}
import os


def run():
    required_vars = ["API_KEY", "WEBHOOK_URL"]

    missing = [var for var in required_vars if not os.getenv(var)]

    if missing:
        return {"error": f"Missing environment variables: {', '.join(missing)}"}

    # Continue with automation
```

### High Failure Rate

Analyze failure patterns:

{/* @sniptest testers/functions/management/high_failure_rate.py */}

```python high_failure_rate.py theme={null}
from notte_sdk import NotteClient

client = NotteClient()

runs = client.functions.list_runs("function_abc123")

failures = [r for r in runs.items if r.status == "failed"]

print(f"Failed runs: {len(failures)}/{len(runs.items)}")

# Analyze failure reasons
for run in failures[:5]:  # Last 5 failures
    print(f"Run {run.workflow_run_id}:")
    print(f"  Error: {run.result}")
    print(f"  Time: {run.created_at}")
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Creating Functions" icon="file-code" href="/features/functions/creating.md">
    Learn how to write Functions
  </Card>

  <Card title="Invocations" icon="play" href="/features/functions/invocations.md">
    Call Functions via API or SDK
  </Card>

  <Card title="Schedules" icon="clock" href="/features/functions/schedules.md">
    Schedule Functions with cron
  </Card>

  <Card title="Functions Concept" icon="lightbulb" href="/concepts/functions.md">
    Back to Functions overview
  </Card>
</CardGroup>
