---
lastModified: 2026-09-18
---

<script>
	import { goto } from '$app/navigation'
	import { page } from '$app/state'

	import LanguageToggle from '$lib/components/language-toggle.svelte'

	const languages = ['typescript', 'python']
	let selectedLanguage = $state(
		languages.includes(page.url.searchParams.get('lang') ?? '')
			? page.url.searchParams.get('lang')
			: 'typescript',
	)
	let isInitialized = false

	function updateURL(lang) {
		const url = new URL(page.url)
		if (url.searchParams.get('lang') !== lang) {
			url.searchParams.set('lang', lang)
			goto(url, { replaceState: true, noScroll: true, keepFocus: true })
		}
	}

	$effect(() => {
		const lang = selectedLanguage
		if (isInitialized) {
			updateURL(lang)
		} else {
			isInitialized = true
		}
	})
</script>

# Amp SDK

The Amp SDK allows you to programmatically use the Amp agent in your TypeScript or Python programs.

<h2 id="why-use-the-amp-sdk">Why use the Amp SDK?</h2>

The Amp SDK offers the following functionality:

- **Stream Inputs**: Send messages one-by-one to the Amp agent
- **Stream Outputs**: Receive structured JSON responses (system, assistant, result) while the agent runs
- **Multi-turn Conversations**: Maintain back-and-forth interactions across multiple inference calls
- **Thread Continuity**: Continue an existing thread (latest or by ID) to build stateful agent workflows
- **Programmatic Settings**: Configure working directories, settings, and tools without user prompts — ideal for automation
- **MCP Integration**: specify which MCP servers are available for a given session
- **Custom Skills**: Define and use custom agent skills to extend Amp's functionality

<h2 id="what-can-you-build">What can you build?</h2>

Here are some examples of what you can build with the Amp SDK:

### Development Tools

- **Code Review Agent**: Automated pull request analysis and feedback
- **Documentation Generator**: Create and maintain project documentation
- **Test Automation**: Generate and execute test suites
- **Migration Assistant**: Help upgrade codebases and refactor legacy code

### Workflow Automation

- **CI/CD Integration**: Smart build and deployment pipelines
- **Issue Triage**: Automatically categorize and prioritize bug reports
- **Code Quality Monitoring**: Continuous analysis of code health metrics
- **Release Management**: Automated changelog generation and version bumping

<h2 id="quick-start">Quick Start</h2>

### Installation

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```bash
# Install the Amp SDK using npm
npm install @ampcode/sdk

# or yarn
yarn add @ampcode/sdk

# Install or upgrade the Amp CLI used by the SDK (optional if a compatible version is already installed)
npx -y @ampcode/sdk install
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```bash
# Install the Amp SDK using pip
pip install amp-sdk

# Install the Amp CLI
curl -fsSL https://ampcode.com/install.sh | bash
```

    	</div>
    {/if}

</div>

For SDK users who need to use Amp before Amp Neo, install the legacy release
[`@ampcode/sdk@0.1.0-20260528044221-ge0e19fa`](https://www.npmjs.com/package/@ampcode/sdk/v/0.1.0-20260528044221-ge0e19fa):

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```bash
npm install @ampcode/sdk@0.1.0-20260528044221-ge0e19fa
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```bash
pip install amp-sdk==0.1.5
npm install -g @ampcode/cli@0.0.1779896748-g596c49
export AMP_CLI_PATH="$(command -v amp)"
```

    	</div>
    {/if}

</div>

For TypeScript SDK users, Amp CLI must be at least the version pinned by the installed SDK release.
If your organization already installs Amp CLI through Homebrew, Artifactory, or another internal
channel, you can keep using it as long as its version is new enough.

Once installed, add your access token to the environment. You can access your access token in
[Security Settings](https://ampcode.com/settings/security#access-token).

```bash
export AMP_API_KEY=sgamp_your_access_token_here
```

If you already have the Amp CLI installed locally, you can log in using the following command `amp login`.

### Run Your First Amp Command

Now that you have the SDK installed and your access token set up, you can start using Amp with the `execute()` function:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
import { execute } from '@ampcode/sdk'

// Simple execution - get the final result
for await (const message of execute({ prompt: 'What files are in this directory?' })) {
	if (message.type === 'result' && !message.is_error) {
		console.log('Result:', message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute

async def main():
    # Simple execution - get the final result
    async for message in execute("What files are in this directory?"):
        if message.type == "result" and not message.is_error:
            print("Result:", message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

The `execute()` function only requires that you provide a `prompt` to get started. The SDK streams messages as the agent works, letting you handle responses and integrate them directly into your application.

<h2 id="core-concepts">Core Concepts</h2>

### Message Streaming

The SDK streams different types of messages as your agent executes:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({ prompt: 'Run tests' })) {
	if (message.type === 'system') {
		// Session info, available tools, MCP servers
		console.log('Available tools:', message.tools)
	} else if (message.type === 'assistant') {
		// AI responses and tool usage
		console.log('Assistant is working...')
	} else if (message.type === 'result') {
		console.log(message.is_error ? `Failed: ${message.error}` : `Done: ${message.result}`)
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute

async def main():
    async for message in execute("Run tests"):
        if message.type == "system":
            # Session info, available tools, MCP servers
            print("Available tools:", message.tools)
        elif message.type == "assistant":
            # AI responses and tool usage
            print("Assistant is working...")
        elif message.type == "result":
            if message.is_error:
                print("Failed:", message.error)
            else:
                print("Done:", message.result)

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Simple Result Extraction

When you just need the final result without handling streaming:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
async function getResult(prompt: string): Promise<string> {
	for await (const message of execute({ prompt, options: {} })) {
		if (message.type === 'result') {
			if (message.is_error) {
				throw new Error(message.error)
			}
			return message.result
		}
	}
	throw new Error('No result received')
}

// Usage
try {
	const result = await getResult('List all TypeScript files in this project')
	console.log('Found files:', result)
} catch (error) {
	console.error('Failed:', error instanceof Error ? error.message : String(error))
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def get_result(prompt: str) -> str:
    async for message in execute(prompt, AmpOptions()):
        if message.type == "result":
            if message.is_error:
                raise Exception(message.error)
            return message.result
    raise Exception("No result received")

# Usage
async def main():
    try:
        result = await get_result("List all Python files in this project")
        print("Found files:", result)
    except Exception as error:
        print("Failed:", str(error))

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Thread Continuity

Continue conversations across multiple interactions:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
// Continue the most recent conversation
for await (const message of execute({
	prompt: 'What was the last error you found?',
	options: { continue: true },
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
	}
}

// Continue a specific thread by ID
for await (const message of execute({
	prompt: 'Can you update that code we discussed?',
	options: { continue: 'T-abc123-def456' },
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    # Continue the most recent conversation
    async for message in execute(
        "What was the last error you found?",
        AmpOptions(continue_thread=True)
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)

    # Continue a specific thread by ID
    async for message in execute(
        "Can you update that code we discussed?",
        AmpOptions(continue_thread="T-abc123-def456")
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)

asyncio.run(main())
```

    	</div>
    {/if}

</div>

<h2 id="common-configuration">Common Configuration</h2>

### Working Directory

Specify where Amp should run:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Refactor the auth module',
	options: { cwd: './my-project' },
})) {
	// Process messages...
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Refactor the auth module",
        AmpOptions(cwd="./my-project")
    ):
        # Process messages...
        pass

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Enable Debug Logging

See what's happening under the hood:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Analyze this project',
	options: {
		logLevel: 'debug', // Shows CLI command in console
		logFile: './amp-debug.log', // Optional: write logs to file
	},
})) {
	// Process messages
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Analyze this project",
        AmpOptions(
            log_level="debug",  # Shows CLI command in console
            log_file="./amp-debug.log"  # Optional: write logs to file
        )
    ):
        # Process messages
        pass

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Agent Mode

Select which agent mode to use. The mode controls the model, system prompt, and tool selection:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Quickly fix this typo',
	options: {
		mode: 'low', // Use low mode for faster responses
	},
})) {
	// Process messages
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Quickly fix this typo",
        AmpOptions(mode="low")  # Use low mode for faster responses
    ):
        # Process messages
        pass

asyncio.run(main())
```

    	</div>
    {/if}

</div>

Available modes:

- `low`: Fast, low-cost mode for small, well-defined tasks
- `medium` (default): Balances quality, speed, and cost for most tasks
- `high`: Deep reasoning for difficult tasks that can tolerate more time and cost
- `ultra`: For the hardest open-ended tasks, when maximum capability matters more than speed or cost

### Reasoning Effort

Set model reasoning effort for supported modes:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Think carefully and explain your plan before coding.',
	options: {
		mode: 'medium',
		effort: 'high',
	},
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Think carefully and explain your plan before coding.",
        AmpOptions(
            mode="medium",
            effort="high",
        ),
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

Available effort levels:

- `none`
- `minimal`
- `low`
- `medium`
- `high`
- `xhigh`
- `max`

### Thread Labels

Add labels to threads created by `execute()`:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Summarize this repo',
	options: {
		labels: ['sdk', 'summary'],
	},
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Summarize this repo",
        AmpOptions(labels=["sdk", "summary"])
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Thread Titles

Set the title when you create a thread. You cannot use `title` when continuing a thread.

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Review pull request 42',
	options: {
		executor: 'orb',
		title: 'Review acme/widgets#42',
	},
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Review pull request 42",
        AmpOptions(
            executor="orb",
            title="Review acme/widgets#42",
        ),
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Remote Executors

By default the agent runs in the local Amp CLI process. Set the executor to `orb` to run it in an
[orb](/docs/orbs), or to `runner` with a runner ID to run it on one of your
[runners](/docs/cli/runners), started with `amp --no-tui --runner-id <id>`. In both cases the local
process only streams the results.
Remote executors need an `AMP_API_KEY`.

For a runner that serves multiple directories, set `runnerDir` in TypeScript or
`runner_dir` in Python to one absolute path on the runner's machine. The runner
must already serve it through `--dir`, discovery, or `amp runner dirs add`. Omit the option to
use the runner's starting directory. Each thread has one working directory, so use separate
`execute()` calls for different directories. Continuing a thread keeps its existing directory.
The `cwd` option only sets the local CLI subprocess directory.

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Run the integration tests and summarize any failures',
	options: {
		executor: 'runner',
		runnerId: 'build-box-1',
		runnerDir: '/home/build/code/my-project',
	},
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Run the integration tests and summarize any failures",
        AmpOptions(
            executor="runner",
            runner_id="build-box-1",
            runner_dir="/home/build/code/my-project",
        ),
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Thread Visibility

Control who can see threads created by `execute()`:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Analyze this private codebase',
	options: {
		visibility: 'private', // Visible only to you (and workspace admins if you're in a workspace)
	},
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
		break
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Analyze this private codebase",
        AmpOptions(visibility="private")  # Visible only to you (and workspace admins if you're in a workspace)
    ):
        if message.type == "result" and not message.is_error:
            print(message.result)
            break

asyncio.run(main())
```

    	</div>
    {/if}

</div>

Available visibility levels:

- `workspace` (default): Visible to all workspace members
- `private`: Visible only to you (and workspace admins if you're in a workspace)
- `unlisted`: Visible to anyone with the link
- `group`: Visible to members of your user group (Enterprise)

### Tool Permissions

Use a [custom plugin](/docs/customize/plugins#example-plugin-permissions) to control tool use.
Workspace admins can distribute it as a
[global workspace plugin](/docs/customize/global-plugins-and-skills#publish-for-everyone).

<h2 id="advanced-usage">Advanced Usage</h2>

### Interactive Progress Tracking

For building user interfaces that show real-time progress:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
async function executeWithProgress(prompt: string) {
	console.log('Starting task...')

	for await (const message of execute({ prompt })) {
		if (message.type === 'system' && message.subtype === 'init') {
			console.log('Tools available:', message.tools.join(', '))
		} else if (message.type === 'assistant') {
			// Show tool usage or assistant responses
			for (const content of message.message.content) {
				if (content.type === 'tool_use') {
					console.log(`Using ${content.name}...`)
				} else if (content.type === 'text') {
					console.log('Assistant:', content.text.slice(0, 100) + '...')
				}
			}
		} else if (message.type === 'result') {
			if (message.is_error) {
				console.log('Failed:', message.error)
			} else {
				console.log('Completed successfully!')
				console.log(message.result)
			}
		}
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
from amp_sdk import execute

async def execute_with_progress(prompt: str):
    print("Starting task...")

    async for message in execute(prompt):
        if message.type == "system" and message.subtype == "init":
            print("Tools available:", ", ".join(message.tools))
        elif message.type == "assistant":
            # Show tool usage or assistant responses
            content = message.message.content[0]
            if content.type == "tool_use":
                print(f"Using {content.name}...")
            elif content.type == "text":
                print("Assistant:", content.text[:100] + "...")
        elif message.type == "result":
            if message.is_error:
                print("Failed:", message.error)
            else:
                print("Completed successfully!")
                print(message.result)
```

    	</div>
    {/if}

</div>

### Cancellation and Timeouts

Handle long-running operations gracefully:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
async function executeWithTimeout(prompt: string, timeoutMs = 30000) {
	const signal = AbortSignal.timeout(timeoutMs)

	try {
		for await (const message of execute({
			prompt,
			signal,
			options: {},
		})) {
			if (message.type === 'result') {
				if (message.is_error) {
					throw new Error(message.error)
				}
				return message.result
			}
		}
	} catch (error) {
		if (signal.aborted) {
			throw new Error(`Operation timed out after ${timeoutMs}ms`)
		}
		throw error
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def consume(prompt: str):
    async for message in execute(prompt, AmpOptions()):
        if message.type == "result":
            if message.is_error:
                raise Exception(message.error)
            return message.result

async def execute_with_timeout(prompt: str, timeout_seconds: float = 30.0):
    try:
        return await asyncio.wait_for(consume(prompt), timeout=timeout_seconds)
    except asyncio.TimeoutError:
        raise Exception(f"Operation timed out after {timeout_seconds}s")
```

    	</div>
    {/if}

</div>

### MCP Integration

Extend Amp's capabilities with custom tools and data sources:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
import { execute, type MCPConfig } from '@ampcode/sdk'

const mcpConfig: MCPConfig = {
	playwright: {
		command: 'npx',
		args: ['-y', '@playwright/mcp@latest', '--headless'],
		env: { NODE_ENV: 'production' },
	},
	database: {
		command: 'node',
		args: ['./custom-mcp-server.js'],
		// ${VAR} placeholders are expanded from Amp's environment at server startup
		env: { DB_CONNECTION_STRING: '${DATABASE_URL}' },
	},
}

for await (const message of execute({
	prompt: 'Test the login flow on staging environment',
	options: { mcpConfig },
})) {
	if (message.type === 'system') {
		console.log(
			'MCP Servers:',
			message.mcp_servers.map((s) => `${s.name}: ${s.status}`),
		)
	}
	// Handle other messages...
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions
from amp_sdk.types import MCPConfig

async def main():
    mcp_config = MCPConfig(
        servers={
            "playwright": {
                "command": "npx",
                "args": ["-y", "@playwright/mcp@latest", "--headless"],
                "env": {"NODE_ENV": "production"}
            },
            "database": {
                "command": "node",
                "args": ["./custom-mcp-server.js"],
                # ${VAR} placeholders are expanded from Amp's environment at server startup
                "env": {"DB_CONNECTION_STRING": "${DATABASE_URL}"}
            }
        }
    )

    async for message in execute(
        "Test the login flow on staging environment",
        AmpOptions(
            mcp_config=mcp_config
        )
    ):
        if message.type == "system":
            print(
                "MCP Servers:",
                [(s.name, s.status) for s in message.mcp_servers]
            )
        # Handle other messages...

asyncio.run(main())
```

    	</div>
    {/if}

</div>

To learn more about extending Amp with MCP servers, see [MCP](/docs/customize/mcp).

### Multi-turn Conversations

Build streaming conversations using async generators:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
import { execute, createUserMessage } from '@ampcode/sdk'

async function* generateMessages() {
	yield createUserMessage('Start analyzing the codebase')

	// Wait for some condition or user input
	await new Promise((resolve) => setTimeout(resolve, 1000))

	yield createUserMessage('Now focus on the authentication module')
}

for await (const message of execute({
	prompt: generateMessages(),
})) {
	if (message.type === 'result' && !message.is_error) {
		console.log(message.result)
	}
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, create_user_message

async def generate_messages():
    yield create_user_message("Start analyzing the codebase")

    # Wait for some condition or user input
    await asyncio.sleep(1)

    yield create_user_message("Now focus on the authentication module")

async def main():
    async for message in execute(generate_messages()):
        if message.type == "result" and not message.is_error:
            print(message.result)

asyncio.run(main())
```

    	</div>
    {/if}

</div>

### Settings File Configuration

Configure Amp's behavior with a settings file, like the `settings.json`. You can provide Amp with a custom settings file you have saved in your project:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
import { execute } from '@ampcode/sdk'

// Use a custom settings file
for await (const message of execute({
	prompt: 'Deploy the application',
	options: {
		settingsFile: './settings.json',
		logLevel: 'debug',
	},
})) {
	// Handle messages...
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    # Use a custom settings file
    async for message in execute(
        "Deploy the application",
        AmpOptions(
            settings_file="./settings.json",
            log_level="debug"
        )
    ):
        # Handle messages...
        pass

asyncio.run(main())
```

    	</div>
    {/if}

</div>

Example `settings.json`:

```json
{
	"amp.mcpServers": {
		"playwright": {
			"command": "npx",
			"args": ["-y", "@playwright/mcp@latest", "--headless", "--isolated"]
		}
	},
	"amp.tools.disable": ["web_search", "mcp__playwright__browser_resize"]
}
```

To find all available settings, see [Configuration](/docs/cli/settings).

### Custom Skills

Load custom skills from a specified directory:

<div class="language-toggle relative">
	<LanguageToggle {languages} bind:selected={selectedLanguage} />
	{#if selectedLanguage === 'typescript'}
		<div class="example typescript">

```typescript
for await (const message of execute({
	prompt: 'Use my custom deployment skill',
	options: {
		skills: './my-skills', // Path to custom skills directory
	},
})) {
	// Process messages
}
```

    	</div>
    {:else if selectedLanguage === 'python'}
    	<div class="example python">

```python
import asyncio
from amp_sdk import execute, AmpOptions

async def main():
    async for message in execute(
        "Use my deployment skill",
        AmpOptions(
            skills="./my-skills"  # Path to custom skills directory
        )
    ):
        # Handle messages...
        pass

asyncio.run(main())
```

    	</div>
    {/if}

</div>

To learn more about creating custom skills, see [Skills](/docs/customize/skills).
