Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions content/docs/integrations/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"...claude-computer-use",
"...crewai",
"...magnitude",
"...morph-computer-use",
"...notte",
"...openai-computer-use",
"...replit",
Expand Down
6 changes: 6 additions & 0 deletions content/docs/integrations/morph-computer-use/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"title": "Morph Computer Use",
"root": false,
"pages": ["---Morph Computer Use---", "quickstart"]
}

300 changes: 300 additions & 0 deletions content/docs/integrations/morph-computer-use/quickstart.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
---
title: Quickstart
sidebarTitle: Quickstart
description: This guide shows how to use Morph Computer Use with Steel to agentically test code changes in full-stack applications using a live cloud browser.
llm: true
---

Morph Computer Use (`morph-computer-use-v0`) is state of the art for agentically testing codegen changes in full-stack applications. It's **10x cheaper** and **250% faster** than general-purpose models like Claude Sonnet, making it ideal for automated testing workflows where you need to verify that code changes work correctly in a real browser environment.

### Requirements
:::prerequisites
* **Steel API key**

* **Morph API key** - Get yours at [morphllm.com](https://morphllm.com)

* **Python 3.11+**
:::

### Step 1: Project Setup and Install Dependencies

```package-install python
steel-sdk browser-use python-dotenv
```


### Step 2: Environment Variables

Create a `.env` file with your API keys and a test task:

```env ENV -wcn -f .env
STEEL_API_KEY=your-steel-api-key-here
MORPH_API_KEY=your-morph-api-key-here
TASK="Test the checkout flow: add an item to cart, proceed to checkout, and verify the order total is displayed correctly"
```


### Step 3: Initialize Steel & Connect via CDP

Set up Steel, load env vars, and prepare to connect Morph via browser-use.

```python Python -wcn -f main.py
import os
import time
import asyncio
from dotenv import load_dotenv
from steel import Steel
from browser_use import Agent, BrowserSession
from browser_use.llm import ChatOpenAI

load_dotenv()

# Replace with your own API keys
STEEL_API_KEY = os.getenv("STEEL_API_KEY") or "your-steel-api-key-here"
MORPH_API_KEY = os.getenv("MORPH_API_KEY") or "your-morph-api-key-here"

# Replace with your own test task
TASK = os.getenv("TASK") or "Test the checkout flow: add an item to cart, proceed to checkout, and verify the order total is displayed correctly"
```


### Step 4: Configure Morph Computer Use Model

Morph is OpenAI-compatible, so we use ChatOpenAI with Morph's endpoint to configure the agent for testing.

```python Python -wcn -f main.py
async def main():
print("🚀 Steel + Morph Computer Use Assistant")
print("=" * 60)

if STEEL_API_KEY == "your-steel-api-key-here":
print("⚠️ WARNING: Please replace 'your-steel-api-key-here' with your actual Steel API key")
print(" Get your API key at: https://app.steel.dev/settings/api-keys")
return

if MORPH_API_KEY == "your-morph-api-key-here":
print("⚠️ WARNING: Please replace 'your-morph-api-key-here' with your actual Morph API key")
print(" Get your API key at: https://morphllm.com")
return
Comment on lines +70 to +78
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Step 4, the code uses return to exit when API keys are invalid, but in the full example (lines 194-202), the same validation uses sys.exit(1). These should be consistent. The full example's approach with sys.exit(1) is more appropriate for a standalone script.

Copilot uses AI. Check for mistakes.

print("\nStarting Steel browser session...")

client = Steel(steel_api_key=STEEL_API_KEY)

try:
session = client.sessions.create()
print("✅ Steel browser session started!")
print(f"View live session at: {session.session_viewer_url}")

cdp_url = f"{session.websocket_url}&apiKey={STEEL_API_KEY}"

# Configure Morph Computer Use model
# Morph is OpenAI-compatible, so we use ChatOpenAI with Morph's endpoint
model = ChatOpenAI(
model="morph-computer-use-v0",
base_url="https://api.morphllm.com/v1",
api_key=MORPH_API_KEY,
temperature=0.3,
)

# Create the agent with Morph model and Steel browser session
agent = Agent(
task=TASK,
llm=model,
browser_session=BrowserSession(cdp_url=cdp_url)
)
```


### Step 5: Run the Test Task

Execute the test task and monitor the results.

```python Python -wcn -f main.py
start_time = time.time()

print(f"🎯 Executing test task: {TASK}")
print("=" * 60)

try:
result = await agent.run()

duration = f"{(time.time() - start_time):.1f}"

print("\n" + "=" * 60)
print("🎉 TEST EXECUTION COMPLETED")
print("=" * 60)
print(f"⏱️ Duration: {duration} seconds")
print(f"🎯 Task: {TASK}")
if result:
print(f"📋 Result:\n{result}")
print("=" * 60)

except Exception as e:
print(f"❌ Test execution failed: {e}")
finally:
if session:
print("Releasing Steel session...")
client.sessions.release(session.id)
print(f"Session completed. View replay at {session.session_viewer_url}")
print("Done!")

except Exception as e:
print(f"❌ Failed to start Steel browser: {e}")
print("Please check your STEEL_API_KEY and internet connection.")


if __name__ == "__main__":
asyncio.run(main())
```


#### Run It

Execute your test automation:

```bash
python main.py
```

You'll see a **session viewer URL** in your console—open it to watch the test execution live.

### Full Example

Complete `main.py` for testing code changes agentically:

```python Python -wc -f main.py
"""
Agentically test code changes in full stack apps using Morph Computer Use with Steel browsers.
https://github.com/steel-dev/steel-cookbook/tree/main/examples/steel-morph-computer-use-starter
"""

import os
import sys
import time
import asyncio
from dotenv import load_dotenv
from steel import Steel
from browser_use import Agent, BrowserSession
from browser_use.llm import ChatOpenAI

load_dotenv()

# Replace with your own API keys
STEEL_API_KEY = os.getenv("STEEL_API_KEY") or "your-steel-api-key-here"
MORPH_API_KEY = os.getenv("MORPH_API_KEY") or "your-morph-api-key-here"

# Replace with your own test task
TASK = os.getenv("TASK") or "Test the checkout flow: add an item to cart, proceed to checkout, and verify the order total is displayed correctly"

async def main():
print("🚀 Steel + Morph Computer Use Assistant")
print("=" * 60)

if STEEL_API_KEY == "your-steel-api-key-here":
print("⚠️ WARNING: Please replace 'your-steel-api-key-here' with your actual Steel API key")
print(" Get your API key at: https://app.steel.dev/settings/api-keys")
sys.exit(1)

if MORPH_API_KEY == "your-morph-api-key-here":
print("⚠️ WARNING: Please replace 'your-morph-api-key-here' with your actual Morph API key")
print(" Get your API key at: https://morphllm.com")
sys.exit(1)

print("\nStarting Steel browser session...")

client = Steel(steel_api_key=STEEL_API_KEY)

try:
session = client.sessions.create()
print("✅ Steel browser session started!")
print(f"View live session at: {session.session_viewer_url}")

print(
f"\033[1;93mSteel Session created!\033[0m\n"
f"View session at \033[1;37m{session.session_viewer_url}\033[0m\n"
)
Comment on lines +210 to +216
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate print statements for the session viewer URL (lines 210-211 and 213-216). The colored version (213-216) appears to be redundant. Consider removing one to avoid repetition.

Copilot uses AI. Check for mistakes.

cdp_url = f"{session.websocket_url}&apiKey={STEEL_API_KEY}"

# Configure Morph Computer Use model
# Morph is OpenAI-compatible, so we use ChatOpenAI with Morph's endpoint
model = ChatOpenAI(
model="morph-computer-use-v0",
base_url="https://api.morphllm.com/v1",
api_key=MORPH_API_KEY,
temperature=0.3,
)

# Create the agent with Morph model and Steel browser session
agent = Agent(
task=TASK,
llm=model,
browser_session=BrowserSession(cdp_url=cdp_url)
)

start_time = time.time()

print(f"🎯 Executing test task: {TASK}")
print("=" * 60)

try:
result = await agent.run()

duration = f"{(time.time() - start_time):.1f}"

print("\n" + "=" * 60)
print("🎉 TEST EXECUTION COMPLETED")
print("=" * 60)
print(f"⏱️ Duration: {duration} seconds")
print(f"🎯 Task: {TASK}")
if result:
print(f"📋 Result:\n{result}")
print("=" * 60)

except Exception as e:
print(f"❌ Test execution failed: {e}")
raise
Comment on lines +256 to +257
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the full example, line 257 re-raises the exception after printing the error, but in Step 5 (line 134), the exception is caught and not re-raised. This inconsistency means Step 5's error handling will suppress exceptions while the full example will propagate them. These should behave consistently.

Copilot uses AI. Check for mistakes.
finally:
if session:
print("Releasing Steel session...")
client.sessions.release(session.id)
print(f"Session completed. View replay at {session.session_viewer_url}")
print("Done!")

except Exception as e:
print(f"❌ Failed to start Steel browser: {e}")
print("Please check your STEEL_API_KEY and internet connection.")
raise
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the full example, line 268 re-raises the exception after printing error details, but in Step 4 (lines 142-144), the exception is caught without re-raising. This creates inconsistent error handling behavior between the step-by-step code and the full example.

Suggested change
raise
raise
raise

Copilot uses AI. Check for mistakes.


if __name__ == "__main__":
asyncio.run(main())

```


### Why Morph Computer Use?

Morph Computer Use is **purpose-built for testing full-stack application changes**. When you make code changes to your app—whether frontend, backend, or both—Morph helps you verify those changes work correctly in a real browser environment.

**Key benefits:**

* **10x cheaper** than general-purpose models like Claude Sonnet
* **250% faster** inference for browser automation tasks
* **Optimized for codegen testing** - Built specifically for validating code changes in full-stack apps
* **Reliable infrastructure** - Steel's cloud browsers provide consistent, scalable testing environments

### Next Steps
:::next-steps
- [Session Lifecycles](/sessions-api/session-lifecycle): Sessions Lifecycle

- [Steel Sessions API](/sessions-api/overview): Sessions API Overview

:::
- **Steel Python SDK**: [https://github.com/steel-dev/steel-python](https://github.com/steel-dev/steel-python)

- **Cookbook example**: [https://github.com/steel-dev/steel-cookbook/tree/main/examples/steel-morph-computer-use-starter](https://github.com/steel-dev/steel-cookbook/tree/main/examples/steel-morph-computer-use-starter)

- **Morph Documentation**: [https://morphllm.com](https://morphllm.com)

Loading