Skyvern/docs/getting-started/ai-agents-quickstart.mdx
Kunal Mishra 0d142cb348
Some checks are pending
Run tests and pre-commit / Run tests and pre-commit hooks (push) Waiting to run
Run tests and pre-commit / Frontend Lint and Build (push) Waiting to run
Publish Fern Docs / run (push) Waiting to run
docs: Multiple fixes for documentation site (#5379)
Co-authored-by: Ritik Sahni <ritiksahni0203@gmail.com>
2026-04-04 12:58:05 +00:00

330 lines
8.8 KiB
Text

---
title: AI Agents Quickstart
subtitle: Give your AI coding assistant full browser automation in one command
slug: getting-started/ai-agents-quickstart
---
export const ApiKeyPrompt = ({ children }) => {
const [apiKey, setApiKey] = useState("");
const [copied, setCopied] = useState(false);
const text = typeof children === "string" ? children : String(children);
const lines = text.split("\n");
const indents = lines.slice(1).filter(l => l.trim()).map(l => l.match(/^(\s*)/)[1].length);
const min = indents.length ? Math.min(...indents) : 0;
const raw = min > 0 ? lines.map((l, i) => i === 0 ? l : l.slice(min)).join("\n") : text;
const content = apiKey ? raw.replace(/PASTE_YOUR_API_KEY_HERE/g, apiKey) : raw;
return (
<div>
<input
type="text"
placeholder="Paste your Skyvern API key"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
spellCheck={false}
autoComplete="off"
style={{
width: "100%",
padding: "10px 14px",
marginBottom: "12px",
borderRadius: "8px",
border: "1px solid var(--border, #d1d5db)",
fontSize: "14px",
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
backgroundColor: "var(--background, transparent)",
color: "inherit",
outline: "none",
boxSizing: "border-box",
}}
/>
<div style={{ position: "relative", borderRadius: "8px", overflow: "hidden" }}>
<button
onClick={async () => {
await navigator.clipboard.writeText(content);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}}
style={{
position: "absolute",
top: "10px",
right: "10px",
padding: "4px 12px",
fontSize: "12px",
borderRadius: "6px",
border: "none",
backgroundColor: "rgba(255, 255, 255, 0.1)",
color: "#a1a1aa",
cursor: "pointer",
zIndex: 1,
}}
>
{copied ? "Copied!" : "Copy"}
</button>
<pre style={{
margin: 0,
padding: "16px",
overflowX: "auto",
fontSize: "13px",
lineHeight: "1.7",
backgroundColor: "#0d1117",
color: "#e6edf3",
}}>
<code>{content}</code>
</pre>
</div>
</div>
);
};
Skyvern lets AI coding assistants (Claude Code, Cursor, Windsurf, Codex) control browsers, extract data, and run workflows.
**Copy the prompt below** into your AI coding agent and you'll have a running automation in minutes.
<Note>
Looking to self-host instead? See the [local installation guide](/getting-started/quickstart) for full setup instructions.
</Note>
## 1. Get your API key
Go to [app.skyvern.com/settings](https://app.skyvern.com/settings) and get your API key.
<Frame>
<img src="/images/get-api-key.png" alt="Skyvern Settings page showing the API Keys section with a masked key and reveal/copy buttons" width="500" />
</Frame>
## 2. Give this prompt to your AI coding agent
Paste your API key below, then copy the prompt into your AI coding assistant.
It will:
1. install the Skyvern Python/Typescript SDK
2. Ask what you want to automate (say "Go to Hacker News and get the top comment of the #1 post" for example)
3. Write the code to a file, and run it.
<Tabs>
<Tab title="Python">
<ApiKeyPrompt>{`Set up Skyvern for browser automation:
1. Install the Skyvern Python SDK (requires Python 3.11, 3.12, or 3.13).
If you hit version errors, use pipx to install in an isolated environment:
pip install skyvern
# or: pipx install skyvern
2. Install all Skyvern skills into this project:
skyvern skill copy --output .claude/skills/
3. Set my API key:
export SKYVERN_API_KEY="PASTE_YOUR_API_KEY_HERE"
Now ask me what I want to automate in the browser. Suggest this as a default:
"Go to Hacker News and get the top comment of the #1 post"
After I respond, create a skyvern-tasks/ folder and save a Python file there
using this template — replace <TASK> and <URL> with what I asked for:
import os
import asyncio
from skyvern import Skyvern
async def main():
client = Skyvern(api_key=os.getenv("SKYVERN_API_KEY"))
result = await client.run_task(
prompt="<TASK>",
url="<URL>",
)
print(f"Task started: {result.run_id}")
print(f"View live: {result.app_url}")
while True:
run = await client.get_run(result.run_id)
print(f"Status: {run.status}")
if run.status in ("completed", "failed", "terminated", "timed_out", "canceled"):
break
await asyncio.sleep(5)
print(f"Final status: {run.status}")
print(f"Output: {run.output}")
if run.recording_url:
print(f"Recording: {run.recording_url}")
asyncio.run(main())
Run the file and show me the output.`}</ApiKeyPrompt>
</Tab>
<Tab title="TypeScript">
<ApiKeyPrompt>{`Set up Skyvern for browser automation:
1. Initialize a Node.js project (if needed) and install the Skyvern TypeScript SDK:
npm init -y
npm install @skyvern/client
2. Set my API key:
export SKYVERN_API_KEY="PASTE_YOUR_API_KEY_HERE"
Now ask me what I want to automate in the browser. Suggest this as a default:
"Go to Hacker News and get the top comment of the #1 post"
After I respond, create a skyvern-tasks/ folder and save a TypeScript file there
using this template — replace <TASK> and <URL> with what I asked for:
import { SkyvernClient } from "@skyvern/client";
async function main() {
const client = new SkyvernClient({
apiKey: process.env.SKYVERN_API_KEY,
});
const result = await client.runTask({
body: {
prompt: "<TASK>",
url: "<URL>",
},
});
console.log(\`Task started: \${result.run_id}\`);
console.log(\`View live: \${result.app_url}\`);
const terminalStatuses = ["completed", "failed", "terminated", "timed_out", "canceled"];
let run;
while (true) {
run = await client.getRun(result.run_id);
console.log(\`Status: \${run.status}\`);
if (terminalStatuses.includes(run.status)) break;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
console.log(\`Final status: \${run.status}\`);
console.log(\`Output: \${JSON.stringify(run.output, null, 2)}\`);
if (run.recording_url) {
console.log(\`Recording: \${run.recording_url}\`);
}
}
main();
Run the file and show me the output.`}</ApiKeyPrompt>
</Tab>
</Tabs>
## 3. Next steps
### Connect the MCP server
Give your AI coding assistant direct browser control through natural language — no SDK code needed.
<Tabs>
<Tab title="Claude Code">
```bash
claude mcp add-json skyvern '{"type":"http","url":"https://api.skyvern.com/mcp/","headers":{"x-api-key":"YOUR_SKYVERN_API_KEY"}}' --scope user
```
</Tab>
<Tab title="Cursor">
Add to `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"Skyvern": {
"type": "streamable-http",
"url": "https://api.skyvern.com/mcp/",
"headers": {
"x-api-key": "YOUR_SKYVERN_API_KEY"
}
}
}
}
```
</Tab>
<Tab title="Windsurf">
Add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"Skyvern": {
"type": "streamable-http",
"url": "https://api.skyvern.com/mcp/",
"headers": {
"x-api-key": "YOUR_SKYVERN_API_KEY"
}
}
}
}
```
</Tab>
<Tab title="Codex">
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.skyvern]
url = "https://api.skyvern.com/mcp/"
[mcp_servers.skyvern.http_headers]
x-api-key = "YOUR_SKYVERN_API_KEY"
```
</Tab>
</Tabs>
### Keep building
<CardGroup cols={3}>
<Card
title="Build a Workflow"
icon="diagram-project"
href="/multi-step-automations/build-a-workflow"
>
Chain multiple steps into a single automation with loops, conditionals, and data passing
</Card>
<Card
title="Extract Structured Data"
icon="database"
href="/running-automations/extract-structured-data"
>
Define a JSON schema to get typed output from your automations
</Card>
<Card
title="Handle Logins"
icon="key"
href="/sdk-reference/credentials"
>
Store credentials securely for sites that require authentication
</Card>
<Card
title="Full MCP Reference"
icon="server"
href="/integrations/mcp"
>
All 33 tools, config options, local mode, and troubleshooting
</Card>
<Card
title="CLI & Skills"
icon="terminal"
href="/integrations/cli"
>
Browser commands, workflow management, and the skill system
</Card>
<Card
title="Use Webhooks"
icon="webhook"
href="/going-to-production/webhooks"
>
Get notified when tasks complete instead of polling
</Card>
</CardGroup>