Skip to main content

Use Shotstack in your own agent

If you're building your own agent, give it Shotstack as a tool. There are two ways.

Connect the MCP server​

If your agent framework supports MCP, connect it to https://mcp.shotstack.io/ and pass your API key in an x-api-key header. Your agent gets every Shotstack tool, including Studio previews, templates and AI generation. See MCP server for the tools and how agents should use them.

Building in n8n? The Shotstack node works as a tool for n8n's AI Agent node. See Automation tools.

Define a render tool​

Otherwise, describe one tool that takes an edit, load the agent guide into the system prompt, and call the Edit API when the model uses the tool. This example uses the Anthropic Python SDK. The same pattern works with OpenAI function calling or any framework that supports tools.

import os
import time

import anthropic
import requests

API = "https://api.shotstack.io/edit/stage" # stage renders are free and watermarked
HEADERS = {"x-api-key": os.environ["SHOTSTACK_API_KEY"]}

# The guide the CLI skill and MCP server use. Fetching it each run picks up new authoring rules as they ship.
guide = requests.get(
"https://raw.githubusercontent.com/shotstack/shotstack-cli/master/skills/shotstack/shared/agent-core.md"
).text

render_tool = {
"name": "render_video",
"description": "Render a Shotstack edit and return the URL of the finished video.",
"input_schema": {
"type": "object",
"properties": {"edit": {"type": "object", "description": "A Shotstack Edit JSON with a timeline and output."}},
"required": ["edit"],
},
}


def render_video(edit):
render_id = requests.post(f"{API}/render", json=edit, headers=HEADERS).json()["response"]["id"]
while True:
render = requests.get(f"{API}/render/{render_id}", headers=HEADERS).json()["response"]
if render["status"] in ("done", "failed"):
return render.get("url") or render.get("error", "Render failed")
time.sleep(5)


client = anthropic.Anthropic()
messages = [{"role": "user", "content": "Make a 10-second video announcing our spring sale."}]

while True:
reply = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=8000,
system=guide,
tools=[render_tool],
messages=messages,
)
messages.append({"role": "assistant", "content": reply.content})
if reply.stop_reason != "tool_use":
break
messages.append({
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": block.id, "content": render_video(block.input["edit"])}
for block in reply.content
if block.type == "tool_use"
],
})

print(reply.content[-1].text)

Polling is the simplest way to wait for a render. In production, set a webhook instead.

Next steps​

  • Once the video is right, save it as a template so your app can render it without the agent. See From draft to production.
  • Give the agent more tools for templates and AI generation, or use the MCP server, which has them already.