The Amp SDK allows you to programmatically use the Amp agent in your TypeScript programs.
The Amp SDK offers the following functionality:
Here are some examples of what you can build with the Amp SDK:
Install the Amp SDK using npm or yarn:
# npm
npm install @sourcegraph/amp-sdk
# yarn
yarn add @sourcegraph/amp-sdk Once installed, add your API key to the environment. You can access your API key at ampcode.com/settings.
export AMP_API_KEY=sgamp_your_api_key_here If you already have the Amp CLI installed locally, you can log in using the following command amp login.
Now that you have the SDK installed and your API key set up, you can start using Amp with the execute() function:
import { execute } from '@sourcegraph/amp-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
}
} 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.
The SDK streams different types of messages as your agent executes:
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') {
// Final result (success or error)
console.log('Done:', message.result)
}
} When you just need the final result without handling streaming:
async function getResult(prompt: string): Promise<string> {
for await (const message of execute({ prompt, options: { dangerouslyAllowAll: true } })) {
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.message)
} Continue conversations across multiple interactions:
// 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') {
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') {
console.log(message.result)
}
} For automation scenarios, bypass permission prompts:
const options = {
dangerouslyAllowAll: true, // Skip permission prompts
}
for await (const message of execute({
prompt: 'Make changes without asking for permission',
options,
})) {
// Handle messages...
} Specify where Amp should run:
for await (const message of execute({
prompt: 'Refactor the auth module',
options: { cwd: './my-project' },
})) {
// Process messages...
} See what’s happening under the hood:
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
} Control which tools Amp can use with fine-grained permissions:
import { execute, createPermission } from '@sourcegraph/amp-sdk'
for await (const message of execute({
prompt: 'List files and run tests',
options: {
permissions: [
// Allow listing files
createPermission('Bash', 'allow', { matches: { cmd: 'ls *' } }),
// Allow running tests
createPermission('Bash', 'allow', { matches: { cmd: 'npm test' } }),
// Ask before reading sensitive files
createPermission('Read', 'ask', { matches: { path: '/etc/*' } }),
],
},
})) {
// Process messages
} Permission rules support:
* wildcards and regex patternsLearn more about permissions in the manual and the appendix.
For building user interfaces that show real-time progress:
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
const content = message.message.content[0]
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)
}
}
}
} Handle long-running operations gracefully:
async function executeWithTimeout(prompt: string, timeoutMs = 30000) {
const signal = AbortSignal.timeout(timeoutMs)
try {
for await (const message of execute({
prompt,
signal,
options: { dangerouslyAllowAll: true },
})) {
if (message.type === 'result') {
return message.result
}
}
} catch (error) {
if (error.message.includes('aborted')) {
throw new Error(`Operation timed out after ${timeoutMs}ms`)
}
throw error
}
} Extend Amp’s capabilities with custom tools and data sources:
import { execute, type MCPConfig } from '@sourcegraph/amp-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'],
env: { DB_CONNECTION_STRING: process.env.DATABASE_URL },
},
}
for await (const message of execute({
prompt: 'Test the login flow on staging environment',
options: { mcpConfig, dangerouslyAllowAll: true },
})) {
if (message.type === 'system') {
console.log(
'MCP Servers:',
message.mcp_servers.map((s) => `${s.name}: ${s.status}`),
)
}
// Handle other messages...
} To find out more about extending Amp with MCP servers, visit the MCP Configuration section of the manual.
Build streaming conversations using async generators:
import { execute, createUserMessage } from '@sourcegraph/amp-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') {
console.log(message.result)
}
} 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:
import { execute } from '@sourcegraph/amp-sdk'
// Use a custom settings file
for await (const message of execute({
prompt: 'Deploy the application',
options: {
settingsFile: './settings.json',
logLevel: 'debug',
},
})) {
// Handle messages...
} Example settings.json:
{
"amp.mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@playwright/mcp@latest", "--headless", "--isolated"]
}
},
"amp.todos.enabled": false,
"amp.commands.allowlist": ["npx", "node", "npm"],
"amp.tools.disable": ["mermaid", "mcp__playwright__browser_resize"]
} To find all available settings, see the Configuration Settings.
Extend Amp’s capabilities with custom toolbox scripts:
for await (const message of execute({
prompt: 'Use my custom deployment scripts',
options: {
toolbox: '/usr/repository-path/toolbox', // Path to toolbox scripts
},
})) {
// Handle messages...
} To find out more about Amp Toolboxes, see the Toolboxes section of the Amp Owner’s Manual.
Complete API reference for the Amp TypeScript SDK. This document provides detailed information about all functions, types, and interfaces.
npm install @sourcegraph/amp-sdk The main function for executing Amp CLI commands programmatically.
function execute(options: ExecuteOptions): AsyncIterable<StreamMessage> Parameters
options (ExecuteOptions) - Configuration for the executionReturns
AsyncIterable<StreamMessage> - Stream of messages from the Amp CLIExample
import { execute } from '@sourcegraph/amp-sdk'
for await (const message of execute({
prompt: 'Analyze this codebase',
options: {
cwd: './my-project',
dangerouslyAllowAll: true,
},
})) {
if (message.type === 'assistant') {
console.log('Assistant:', message.message.content)
} else if (message.type === 'result') {
console.log('Final result:', message.result)
break
}
} Helper function to create properly formatted user input messages for streaming conversations.
function createUserMessage(text: string): UserInputMessage Parameters
text (string) - The text content for the user messageReturns
UserInputMessage - A formatted user input messageExample
import { createUserMessage } from '@sourcegraph/amp-sdk'
const message = createUserMessage('Analyze this code')
console.log(message)
// Output: { type: 'user', message: { role: 'user', content: [{ type: 'text', text: 'Analyze this code' }] } } Helper function to create permission objects for controlling tool usage.
function createPermission(
tool: string,
action: 'allow' | 'reject' | 'ask' | 'delegate',
options?: {
matches?: Record<string, PermissionMatchCondition>
context?: 'thread' | 'subagent'
to?: string
},
): Permission Parameters
tool (string) - The name of the tool to which this permission applies (supports glob patterns)action ('allow' | 'reject' | 'ask' | 'delegate') - How Amp should proceed when matchedoptions (object, optional) - Additional configuration for the permission matches (Record<string, PermissionMatchCondition>) - Match conditions for tool argumentscontext ('thread' | 'subagent') - Only apply this rule in specific contextto (string) - Command to delegate to (required when action is 'delegate')Returns
Permission - A permission object that can be used in the permissions arrayExamples
import { createPermission } from '@sourcegraph/amp-sdk'
// Allow all Bash commands
createPermission('Bash', 'allow')
// Allow specific git commands
createPermission('Bash', 'allow', {
matches: { cmd: 'git *' },
})
// Ask before allowing Read operations on sensitive paths
createPermission('Read', 'ask', {
matches: { path: '/etc/*' },
})
// Delegate web browsing to a custom command
createPermission('mcp__playwright__*', 'delegate', {
to: 'node browse.js',
})
// Only apply in subagent context
createPermission('Bash', 'reject', {
context: 'subagent',
}) Configuration options for the execute() function.
interface ExecuteOptions {
prompt: string | AsyncIterable<UserInputMessage>
options?: AmpOptions
signal?: AbortSignal
} Properties
| Property | Type | Required | Description |
|---|---|---|---|
prompt | string \| AsyncIterable<UserInputMessage> | Yes | The input prompt as a string or async iterable of user messages for multi-turn conversations |
options | AmpOptions | No | CLI configuration options |
signal | AbortSignal | No | Signal for cancellation support |
Configuration options that map to Amp CLI flags.
interface AmpOptions {
cwd?: string
dangerouslyAllowAll?: boolean
visibility?: 'public' | 'private' | 'team'
settingsFile?: string
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'audit'
logFile?: string
mcpConfig?: string | MCPConfig
env?: Record<string, string>
continue?: boolean | string
toolbox?: string
permissions?: Permission[]
} Properties
| Property | Type | Default | Description |
|---|---|---|---|
cwd | string | process.cwd() | Current working directory for execution |
dangerouslyAllowAll | boolean | false | Allow all tool usage without permission prompts |
visibility | 'public' \| 'private' \| 'team' | 'team' | Thread visibility level |
settingsFile | string | - | Path to custom settings file |
logLevel | 'debug' \| 'info' \| 'warn' \| 'error' \| 'audit' | 'info' | Logging verbosity level |
logFile | string | - | Path to write logs |
continue | boolean \| string | false | Continue most recent thread (true) or specific thread by ID (string) |
mcpConfig | string \| MCPConfig | - | MCP server configuration as JSON string, or config object |
env | Record<string, string> | - | Additional environment variables |
toolbox | string | - | Folder path with toolbox scripts |
permissions | Permission[] | - | Permission rules for tool usage |
The SDK streams various message types during execution. All messages implement the base StreamMessage type.
Initial message containing session information and available tools.
interface SystemMessage {
type: 'system'
subtype: 'init'
session_id: string
cwd: string
tools: string[]
mcp_servers: Array<{
name: string
status: 'connected' | 'connecting' | 'connection-failed'
}>
} Properties
| Property | Type | Description |
|---|---|---|
session_id | string | Unique identifier for this execution session |
cwd | string | Current working directory |
tools | string[] | List of available tool names |
mcp_servers | Array<{name: string, status: string}> | Status of MCP servers |
AI assistant responses with text content and tool usage.
interface AssistantMessage {
type: 'assistant'
session_id: string
message: {
id: string
type: 'message'
role: 'assistant'
model: string
content: Array<TextContent | ToolUseContent>
stop_reason: 'end_turn' | 'tool_use' | 'max_tokens' | null
stop_sequence: string | null
usage?: Usage
}
parent_tool_use_id: string | null
} Properties
| Property | Type | Description |
|---|---|---|
session_id | string | Unique identifier for this execution session |
message | object | The assistant’s message content |
parent_tool_use_id | string \| null | ID of parent tool use if this is a tool response |
User input and tool results.
interface UserMessage {
type: 'user'
session_id: string
message: {
role: 'user'
content: Array<TextContent | ToolResultContent>
}
parent_tool_use_id: string | null
} Properties
| Property | Type | Description |
|---|---|---|
session_id | string | Unique identifier for this execution session |
message | object | The user’s message content |
parent_tool_use_id | string \| null | ID of parent tool use if this is a tool response |
Final successful execution result.
interface ResultMessage {
type: 'result'
subtype: 'success'
session_id: string
is_error: false
result: string
duration_ms: number
num_turns: number
usage?: Usage
permission_denials?: string[]
} Properties
| Property | Type | Description |
|---|---|---|
session_id | string | Unique identifier for this execution session |
result | string | The final result from the assistant |
duration_ms | number | Total execution time in milliseconds |
num_turns | number | Number of conversation turns |
usage | Usage | Token usage information |
permission_denials | string[] | List of permissions that were denied |
Final error result indicating execution failure.
interface ErrorResultMessage {
type: 'result'
subtype: 'error_during_execution' | 'error_max_turns'
session_id: string
is_error: true
error: string
duration_ms: number
num_turns: number
usage?: Usage
permission_denials?: string[]
} Properties
| Property | Type | Description |
|---|---|---|
session_id | string | Unique identifier for this execution session |
error | string | Error message describing what went wrong |
duration_ms | number | Total execution time in milliseconds |
num_turns | number | Number of conversation turns |
usage | Usage | Token usage information |
permission_denials | string[] | List of permissions that were denied |
Plain text content block.
interface TextContent {
type: 'text'
text: string
} Tool execution request.
interface ToolUseContent {
type: 'tool_use'
id: string
name: string
input: Record<string, unknown>
} Result from tool execution.
interface ToolResultContent {
type: 'tool_result'
tool_use_id: string
content: string
is_error: boolean
} Token usage and billing information from API calls.
interface Usage {
input_tokens: number
cache_creation_input_tokens?: number
cache_read_input_tokens?: number
output_tokens: number
service_tier?: string
} Properties
| Property | Type | Description |
|---|---|---|
input_tokens | number | Number of input tokens used |
cache_creation_input_tokens | number | Tokens used for cache creation |
cache_read_input_tokens | number | Tokens read from cache |
output_tokens | number | Number of output tokens generated |
service_tier | string | Service tier used for this request |
Formatted user input message for streaming conversations.
interface UserInputMessage {
type: 'user'
message: {
role: 'user'
content: Array<{
type: 'text'
text: string
}>
}
} Configuration for MCP (Model Context Protocol) servers.
type MCPConfig = Record<string, MCPServer>
interface MCPServer {
command: string
args?: string[]
env?: Record<string, string>
} Properties
| Property | Type | Required | Description |
|---|---|---|---|
command | string | Yes | Command to start the MCP server |
args | string[] | No | Command line arguments |
env | Record<string, string> | No | Environment variables for the server |
Individual permission rule for controlling tool usage.
interface Permission {
tool: string
matches?: Record<string, PermissionMatchCondition>
action: 'allow' | 'reject' | 'ask' | 'delegate'
context?: 'thread' | 'subagent'
to?: string
} Properties
| Property | Type | Required | Description |
|---|---|---|---|
tool | string | Yes | Tool name (supports glob patterns like Bash or mcp__*) |
matches | Record<string, PermissionMatchCondition> | No | Match conditions for tool arguments |
action | 'allow' \| 'reject' \| 'ask' \| 'delegate' | Yes | How Amp should proceed when the rule matches |
context | 'thread' \| 'subagent' | No | Apply rule only in main thread or sub-agents |
to | string | No | Command to delegate to (required when action is delegate) |
Example
import { execute, createPermission } from '@sourcegraph/amp-sdk'
for await (const message of execute({
prompt: 'Deploy the application',
options: {
permissions: [
// Allow git commands
createPermission('Bash', 'allow', { matches: { cmd: 'git *' } }),
// Allow reading files
createPermission('Read', 'allow'),
],
},
})) {
// Handle messages
} Match condition for tool arguments. Supports strings (with glob patterns or regex), arrays (OR logic), booleans, numbers, null, undefined, and nested objects.
type PermissionMatchCondition =
| string
| PermissionMatchCondition[]
| { [key: string]: PermissionMatchCondition }
| boolean
| number
| null
| undefined Examples
// String pattern with wildcard
{ cmd: 'npm *' }
// Array for OR logic
{ cmd: ['npm install', 'npm test', 'npm run build'] }
// Regex pattern
{ cmd: '/^git (status|log|diff)$/' }
// Nested object matching
{ env: { NODE_ENV: 'production' } }