Cloudflare Artifacts: Git storage built for AI agents
By Flavio Copes
Learn how Cloudflare Artifacts gives AI agents isolated Git repositories, short-lived access tokens, forks, and a programmable Workers API.
AI coding agents create a lot of files.
They edit code, generate configuration, run experiments, and produce results. We need a place where all this work can live.
A temporary folder works until the process disappears. Object storage keeps files, but it does not give us commits, branches, or diffs. GitHub gives us Git, but creating thousands of small repositories for short-lived agents is not its main job.
Cloudflare Artifacts is built for this problem.
It gives every agent a real Git repository, with standard clone, pull, and push commands. But those repositories are also programmable from a Cloudflare Worker or the REST API.
Artifacts is currently in beta. You need access enabled on your Cloudflare account before following this tutorial.
People are already using it at scale. Dillon Mulroy from Cloudflare says Artifacts is nearing 50,000 new repositories per day.
That’s the interesting shift. A repository is no longer something a team creates occasionally. An application can create one for every agent, task, or experiment, then keep or delete it when the work is done.
What is Cloudflare Artifacts?
Artifacts is versioned, Git-compatible storage.
Each repository has:
- its own Git history and branches
- a stable HTTPS remote
- separate read and write tokens
- durable storage replicated by Cloudflare
Repositories live inside namespaces. A namespace is a container you can use for an environment, a customer, or a group of agents.
For example:
agents/
agent-001
agent-002
agent-003
You don’t create the agents namespace separately. Artifacts creates it when you add the first repository.
Create your first repository
The simplest way to start is through Wrangler.
First, log in:
npx wrangler login
Now create a repository called agent-001 inside the agents namespace:
npx wrangler artifacts repos create agent-001 \
--namespace agents \
--default-branch main
You can inspect it with:
npx wrangler artifacts repos get agent-001 \
--namespace agents
Wrangler prints the repository details, including its Git remote.
It looks like this:
https://<ACCOUNT_ID>.artifacts.cloudflare.net/git/agents/agent-001.git
Create a write token
Every repository has its own tokens. A read token can clone, fetch, and pull. A write token can also push.
Let’s create a write token that expires after one hour:
npx wrangler artifacts repos issue-token agent-001 \
--namespace agents \
--scope write \
--ttl 3600
Copy the remote and token into two shell variables:
export ARTIFACTS_REMOTE='https://<ACCOUNT_ID>.artifacts.cloudflare.net/git/agents/agent-001.git'
export ARTIFACTS_TOKEN='art_v1_<TOKEN>?expires=<TIMESTAMP>'
Treat the token like a password. Do not commit it or print it in logs.
Push a commit
Now let’s create a small local repository:
mkdir agent-work
cd agent-work
git init -b main
printf '# Work produced by agent-001\n' > README.md
git add README.md
git commit -m "Add initial result"
git remote add origin "$ARTIFACTS_REMOTE"
Push the commit using the token:
git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" \
push -u origin main
This is a normal Git push. Artifacts speaks the Git smart HTTP protocol, so your existing Git client works without a plugin.
Notice that we did not put the token in the remote URL. The http.extraHeader option sends it only for this command.
You can clone the repository in the same way:
git -c http.extraHeader="Authorization: Bearer $ARTIFACTS_TOKEN" \
clone "$ARTIFACTS_REMOTE" agent-work-copy
Create repositories from a Worker
The CLI is useful for us. The Workers binding is useful when your application needs to create repositories automatically.
Create a Worker:
npm create cloudflare@latest artifacts-worker
cd artifacts-worker
Choose a Worker-only TypeScript project.
Add the Artifacts binding to wrangler.jsonc:
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "artifacts-worker",
"main": "src/index.ts",
"compatibility_date": "2026-07-10",
"artifacts": [
{
"binding": "ARTIFACTS",
"namespace": "agents"
}
]
}
Generate the binding types:
npx wrangler types
Now replace src/index.ts with this:
interface Env {
ARTIFACTS: Artifacts
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url)
if (request.method !== 'POST' || url.pathname !== '/repos') {
return new Response('Use POST /repos', { status: 404 })
}
const created = await env.ARTIFACTS.create('agent-002', {
description: 'Workspace for agent-002',
setDefaultBranch: 'main',
})
return Response.json({
name: created.name,
remote: created.remote,
token: created.token,
})
},
} satisfies ExportedHandler<Env>
Start the Worker:
npx wrangler dev
Then create the repository from another terminal:
curl -X POST http://localhost:8787/repos
The response contains the repository name, remote URL, and initial write token:
{
"name": "agent-002",
"remote": "https://<ACCOUNT_ID>.artifacts.cloudflare.net/git/agents/agent-002.git",
"token": "art_v1_<TOKEN>?expires=<TIMESTAMP>"
}
The example returns a write token to keep the flow visible. Do not expose this endpoint publicly without authentication.
In production, verify the caller first. Create short-lived read tokens for clone operations, and only create write tokens when a client must push.
Give every agent its own fork
One useful pattern is to keep a baseline repository, then fork it for every task.
The agent starts with the same files, but works in isolation:
const baseline = await env.ARTIFACTS.get('project-baseline')
const fork = await baseline.fork('agent-003', {
description: 'Isolated workspace for agent-003',
defaultBranchOnly: true,
})
console.log(fork.remote)
The fork gets its own history, tokens, and lifecycle. Changes made by agent-003 do not affect the baseline.
When the work is done, your application can inspect the commits or diff the result. It can keep the repository as an audit trail, or delete it.
Import an existing GitHub repository
You can also import a public Git repository:
const imported = await env.ARTIFACTS.import({
source: {
url: 'https://github.com/cloudflare/workers-sdk',
branch: 'main',
depth: 1,
},
target: {
name: 'workers-sdk-copy',
},
})
console.log(imported.remote)
A shallow import is useful when an agent needs the current code, but not the entire history.
Where Artifacts fits
Artifacts is not a GitHub replacement.
GitHub is where people collaborate through issues, pull requests, reviews, and releases. Artifacts is a programmable Git storage layer for applications, automations, and agents.
It is a good fit when you need:
- one isolated repository per agent or task
- versioned generated content
- Git-backed configuration history
- temporary forks for code experiments
- repositories created from application code
If you only need to store files, R2 is simpler. Use Artifacts when commits, branches, diffs, and rollback are part of the data model.
Current limits
At the time of writing, each repository can store up to 10 GB. An account gets 1 TB total by default, and Cloudflare says this can be raised on request.
The number of repositories and namespaces is unlimited. Both control-plane and per-repository Git operations allow 2,000 requests per 10 seconds.
Check the current limits before designing around those numbers. Artifacts is still in beta, so they can change.
The interesting part
Agents already know Git.
They know how to clone a repository, create a branch, commit files, inspect a diff, and push the result. Artifacts doesn’t invent a new filesystem API for that workflow.
It gives agents the interface they already understand, while giving us an API to create and control repositories at scale.
That’s the part I find interesting. The storage is useful, but the real idea is simpler: give every agent an isolated place to work, and make the handoff a Git remote.
Related posts about cloudflare: