Overview
The Agents API allows you to create, manage, and deploy AI agents on the Runloop platform. Agents can be sourced from Git repositories, npm packages, PyPI packages, or Runloop Objects. Once created, agents can be mounted to Devboxes and used in your workflows.
Why Use Agent Objects?
Registering an agent with the Agents API gives you control over how agents are installed, versioned, and distributed. There are three common motivations:
Fast, reliable installs. Every time a devbox starts, the agent needs to be ready. Downloading dependencies from external servers on every launch introduces latency and risk — package registries can be slow, rate-limited, or temporarily unavailable. Object-based agents solve this by bundling everything into a pre-packaged archive stored on Runloop, eliminating wide-area network traffic entirely. Git and package-based agents still fetch from upstream servers, but registering them as Runloop agents caches metadata and streamlines the install process.
Explicit version control. You want to know exactly which version of an agent is running. Each source type supports this differently:
- Git agents can pin to a specific branch or tag via the
ref field
- npm/pip agents use standard lock files (
package-lock.json, requirements.txt with pinned versions) to freeze the dependency tree
- Object-based agents are inherently immutable — the archive you upload is exactly what gets installed
Publishing and distribution. You may want to publish an agent from your source repository for internal or external use, with regular releases. The Agents API provides a central registry where you can create versioned agent entries, making it easy to reference them by name or ID when creating devboxes. Combined with the deploy-agent GitHub Action, you can automate publishing new agent versions on every release.
Agent Source Types
Runloop supports four types of agent sources. Choose the one that best matches how your agent is developed, versioned, and deployed.
| Source Type | Description | Best For |
|---|
| Git | Clone from a Git repository | Agents in active development, or when you need to target a specific branch or commit |
| npm | Install from npm registry | Node.js agents with stable, versioned releases on npm |
| pip | Install from PyPI | Python agents with stable, versioned releases on PyPI |
| Object | Unpack from a Runloop storage object | Pre-packaged bundles, compiled agents, or production workloads needing fast deterministic startup |
Package-based agents (pip / npm) are the simplest option when the agent is already published to a registry and follows conventional release practices. Package installation integrates cleanly with existing dependency management workflows.Git-based agents give you tighter control — run directly from source, target a specific commit, and customize build or runtime behavior. Especially useful during active development or for internal agents that aren’t published to a registry.Object-based agents eliminate external dependencies at startup. By packaging the agent ahead of time and storing it as a Runloop Object, you avoid repeated downloads and build steps. Well suited for agents with complex build pipelines, agents written in compiled languages, or any workload where fast startup matters.
Creating Agents
Creating an Agent from a Git Repository
Create an agent by cloning a Git repository. This is ideal for custom agents or open source agents hosted on GitHub.
import asyncio
from runloop_api_client import AsyncRunloopSDK
runloop = AsyncRunloopSDK()
agent = await runloop.agent.create(
name="my-git-agent",
source={
"type": "git",
"git": {
"repository": "https://github.com/username/my-agent-repo",
"ref": "main", # Optional: branch or tag
"agent_setup": [ # Optional: commands to run after clone
"npm install"
]
}
}
)
print(f"Created agent: {agent.id}")
print(f"Agent name: {agent.name}")
import { RunloopSDK } from '@runloop/api-client';
const runloop = new RunloopSDK();
const agent = await runloop.agent.create({
name: 'my-git-agent',
source: {
type: 'git',
git: {
repository: 'https://github.com/username/my-agent-repo',
ref: 'main', // Optional: branch or tag
agentSetup: [ // Optional: commands to run after clone
'npm install'
]
}
}
});
console.log(`Created agent: ${agent.id}`);
console.log(`Agent name: ${agent.name}`);
Creating an Agent from an npm Package
Create an agent from an npm package. The package will be installed globally when the devbox is created. Use the top-level version field to pin a specific package version — when omitted, the latest version from the registry is installed.
agent = await runloop.agent.create(
name="my-npm-agent",
version="2.1.123", # Optional: pin package version
source={
"type": "npm",
"npm": {
"package_name": "@anthropic-ai/claude-code",
"registry_url": None, # Optional: custom registry URL
"agent_setup": [ # Optional: commands to run after install
"echo 'Agent installed'"
]
}
}
)
print(f"Created agent: {agent.id}")
const agent = await runloop.agent.create({
name: 'my-npm-agent',
version: '2.1.123', // Optional: pin package version
source: {
type: 'npm',
npm: {
packageName: '@anthropic-ai/claude-code',
registryUrl: undefined, // Optional: custom registry URL
agentSetup: [ // Optional: commands to run after install
'echo "Agent installed"'
]
}
}
});
console.log(`Created agent: ${agent.id}`);
Creating an Agent from a PyPI Package
Create an agent from a PyPI package. The package will be installed globally when the devbox is created. Use the top-level version field to pin a specific package version — when omitted, the latest version from the registry is installed.
agent = await runloop.agent.create(
name="my-pip-agent",
version="1.5.0", # Optional: pin package version
source={
"type": "pip",
"pip": {
"package_name": "my-agent-package",
"registry_url": None, # Optional: custom registry URL
"agent_setup": [ # Optional: commands to run after install
"my-agent --setup"
]
}
}
)
print(f"Created agent: {agent.id}")
const agent = await runloop.agent.create({
name: 'my-pip-agent',
version: '1.5.0', // Optional: pin package version
source: {
type: 'pip',
pip: {
packageName: 'my-agent-package',
registryUrl: undefined, // Optional: custom registry URL
agentSetup: [ // Optional: commands to run after install
'my-agent --setup'
]
}
}
});
console.log(`Created agent: ${agent.id}`);
Creating an Agent from a Storage Object
Create an agent from a Runloop Object. This is useful for pre-packaged agent bundles, custom builds, or agents that require specific file structures.
Before creating an object-based agent, you need to upload your agent files as a Runloop Object. See the Runloop Objects documentation for details on creating objects.
Step 1: Upload Agent Files as a Runloop Object
First, package your agent files and upload them as an object. You can upload a tar archive (.tar, .tar.gz, .tgz) or a single file.
# Option 1: Upload a tar archive containing your agent files
runloop_object = await runloop.storage_object.upload_from_file(
file_path='./my-agent.tar.gz',
name='my-agent-bundle.tar.gz'
)
# Option 2: Upload a single file
runloop_object = await runloop.storage_object.upload_from_text(
text='#!/usr/bin/env python3\nprint("Hello from agent")',
name='agent.py'
)
object_id = runloop_object.id
print(f"Uploaded object: {object_id}")
// Option 1: Upload a tar archive containing your agent files
const runloopObject = await runloop.storageObject.uploadFromFile(
'./my-agent.tar.gz',
'my-agent-bundle.tar.gz'
);
// Option 2: Upload a single file
const runloopObject = await runloop.storageObject.uploadFromText(
'#!/usr/bin/env python3\nconsole.log("Hello from agent")',
'agent.js'
);
const objectId = runloopObject.id;
console.log(`Uploaded object: ${objectId}`);
Setup Command Working Directory
The working directory for agent_setup commands depends on the object’s content type:
| Content Type | Working Directory | Example |
|---|
| Single files (binary, text, gzip, etc.) | The parent directory of agent_path | If agent_path is /home/user/agent.bin, commands run in /home/user/ |
.tar, .tar.gz, .tgz | The agent_path itself (the extracted directory) | Commands run inside the unpacked archive |
git agents | The agent_path itself (the extracted directory) | Commands run inside the git repository |
pip/npm agents do not have agent_setup commands.
Step 2: Create Agent from Runloop Object
Once you have the object ID, create an agent using the object source. You can optionally provide setup commands to run after unpacking the object.
agent = await runloop.agent.create(
name="my-object-agent",
source={
"type": "object",
"object": {
"object_id": object_id,
"agent_setup": [
"chmod +x agent.py",
"pip install -r requirements.txt"
]
}
}
)
print(f"Created agent: {agent.id}")
const agent = await runloop.agent.create({
name: 'my-object-agent',
source: {
type: 'object',
object: {
objectId: objectId,
agentSetup: [
'chmod +x agent.js',
'npm install'
]
}
}
});
console.log(`Created agent: ${agent.id}`);
Complete Example: Creating an Object-Based Agent
Here’s a complete example that packages agent files, uploads them, and creates an agent:
import asyncio
import tarfile
from runloop_api_client import AsyncRunloopSDK
runloop = AsyncRunloopSDK()
async def create_object_agent():
# Step 1: Package agent files into a tar archive
with tarfile.open('agent-bundle.tar.gz', 'w:gz') as tar:
tar.add('agent.py', arcname='agent.py')
tar.add('requirements.txt', arcname='requirements.txt')
tar.add('config.json', arcname='config.json')
# Step 2: Upload the archive as a storage object
storage_object = await runloop.storage_object.upload_from_file(
file_path='./agent-bundle.tar.gz',
name='agent-bundle.tar.gz'
)
# Step 3: Create agent from the storage object
agent = await runloop.agent.create(
name="my-packaged-agent",
source={
"type": "object",
"object": {
"object_id": storage_object.id,
"agent_setup": [
"pip install -r requirements.txt",
"chmod +x agent.py"
]
}
}
)
print(f"Created agent: {agent.id}")
print(f"Agent name: {agent.name}")
return agent
asyncio.run(create_object_agent())
import { RunloopSDK } from '@runloop/api-client';
import * as tar from 'tar';
import * as fs from 'fs';
const runloop = new RunloopSDK();
async function createObjectAgent() {
// Step 1: Package agent files into a tar archive
await tar.create(
{ gzip: true, file: 'agent-bundle.tar.gz' },
['agent.js', 'package.json', 'config.json']
);
// Step 2: Upload the archive as a storage object
const storageObject = await runloop.storageObject.uploadFromFile(
'./agent-bundle.tar.gz',
'agent-bundle.tar.gz'
);
// Step 3: Create agent from the storage object
const agent = await runloop.agent.create({
name: 'my-packaged-agent',
source: {
type: 'object',
object: {
objectId: storageObject.id,
agentSetup: [
'npm install',
'chmod +x agent.js'
]
}
}
});
console.log(`Created agent: ${agent.id}`);
console.log(`Agent name: ${agent.name}`);
return agent;
}
createObjectAgent();
Public Agents
Runloop provides ready-to-use public wrappers for popular coding agents like Claude Code, Codex, OpenCode, Gemini CLI, and DeepAgents.
You can list all available public agents:
public_agents = await runloop.agent.list_public()
for agent in public_agents.agents:
print(f"{agent.name} v{agent.version}")
const publicAgents = await runloop.agent.listPublic();
publicAgents.agents?.forEach(agent => {
console.log(`${agent.name} v${agent.version}`);
});
Public agents can be mounted by name when creating a devbox. See Agent Mounts — Public Agents for usage examples.
Retrieving Agents
Get a Specific Agent
Retrieve details about a specific agent by its ID.
agent = await runloop.agent.from_id('agt_abc123xyz')
agent_details = await agent.get_info()
print(f"Agent ID: {agent_details.id}")
print(f"Agent name: {agent_details.name}")
print(f"Agent version: {agent_details.version}")
print(f"Source type: {agent_details.source.type if agent_details.source else 'None'}")
const agent = await runloop.agent.fromId('agt_abc123xyz');
const agentDetails = await agent.getInfo();
console.log(`Agent ID: ${agentDetails.id}`);
console.log(`Agent name: ${agentDetails.name}`);
console.log(`Agent version: ${agentDetails.version}`);
console.log(`Source type: ${agentDetails.source?.type || 'None'}`);
Listing Agents
List Your Agents
Retrieve a list of all agents in your account.
agents_list = await runloop.agent.list(limit=20)
print(f"Total agents: {agents_list.total_count}")
for agent in agents_list.agents:
print(f"- {agent.name} (ID: {agent.id}, Version: {agent.version})")
const agentsList = await runloop.agent.list({ limit: 20 });
console.log(`Total agents: ${agentsList.totalCount}`);
agentsList.agents?.forEach(agent => {
console.log(`- ${agent.name} (ID: ${agent.id}, Version: ${agent.version})`);
});
Agent Versioning
How you control which version of an agent is installed depends on the source type:
- Git agents use the
ref field to pin to a specific branch or tag. The top-level version field is not used.
- npm/pip agents use the top-level
version field to pin the installed package version (e.g., "2.1.123"). When omitted, the latest version from the registry is installed.
- Object agents are inherently immutable — each upload produces a new object ID. The
version field is not used.
# Git agent: use ref to pin a version
agent_tag = await runloop.agent.create(
name="my-agent",
source={"type": "git", "git": {"repository": "https://github.com/user/repo", "ref": "v1.0.0"}}
)
# npm agent: pin to a specific package version
agent_npm = await runloop.agent.create(
name="my-npm-agent",
version="2.1.123",
source={"type": "npm", "npm": {"package_name": "@anthropic-ai/claude-code"}}
)
# npm agent: install latest version (omit version)
agent_npm_latest = await runloop.agent.create(
name="my-npm-agent",
source={"type": "npm", "npm": {"package_name": "@anthropic-ai/claude-code"}}
)
// Git agent: use ref to pin a version
const agentTag = await runloop.agent.create({
name: 'my-agent',
source: { type: 'git', git: { repository: 'https://github.com/user/repo', ref: 'v1.0.0' } }
});
// npm agent: pin to a specific package version
const agentNpm = await runloop.agent.create({
name: 'my-npm-agent',
version: '2.1.123',
source: { type: 'npm', npm: { packageName: '@anthropic-ai/claude-code' } }
});
// npm agent: install latest version (omit version)
const agentNpmLatest = await runloop.agent.create({
name: 'my-npm-agent',
source: { type: 'npm', npm: { packageName: '@anthropic-ai/claude-code' } }
});
Using Agents with Devboxes
Once you’ve created an agent, you can mount it onto a Devbox. See the Agent Mounts documentation for details on using agents with Devboxes.
# Create a devbox with an agent mount
devbox = await runloop.devbox.create(
mounts=[
{
"type": "agent_mount",
"agent_name": "my-agent",
# "agent_id": "agt_abc123xyz",
# Use one of agent_name or agent_id. When using agent_name the most recently created agent with a matching name will be used.
"agent_path": "/home/user/agent"
}
]
)
// Create a devbox with an agent mount
const devbox = await runloop.devbox.create({
mounts: [
{
type: 'agent_mount',
agentName: 'my-agent',
// "agentId: 'agt_abc123xyz',
// Use one of agentName or agentId. When using agentName the most recently created agent with a matching name will be used.
agentPath: '/home/user/agent'
}
]
});
Best Practices
Agent Naming
-
Use descriptive names: Choose clear, meaningful names for your agents
- ✅
code-review-agent
- ❌
agent1
-
Use consistent versioning: For git agents, use meaningful tags as the
ref. For npm/pip agents, use version to pin the installed package version.
Source Type Selection
- Git: Best for version-controlled agents, custom development, open source agents
- npm: Best for Node.js-based agents available on npm
- pip: Best for Python-based agents available on PyPI
- Object: Best for pre-packaged agents, custom builds, or agents with complex dependencies
Object-Based Agents
- Include setup commands: Use
agent_setup to automate installation and configuration
- Check compatibility: Object-based agents are particularly useful when developing agents in compiled languages. Make sure that any compiled binaries work on all target platforms.
Security
- Private repositories: Use authentication tokens for private Git repositories
- Sensitive data: Avoid storing secrets or API keys in agent packages and within Runloop Objects