OpenCurro-ai
Health Warn
- No license — Repository has no license file
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 6 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
OpenCurro AI Agent is a fast, lightweight, and autonomous general-purpose AI agent. An open alternative to OpenClaw, Manus, and Genspark, built to complete real-world tasks efficiently.
╔══════════════════════════════════════════════╗ ║ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ║ ║ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔══██╗ ║ ║ ██████╔╝██████╔╝██████╔╝██████╔╝██████╔╝ ║ ║ ██╔═══╝ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗ ║ ║ ██║ ██║ ██║██║ ██║██║ ██║██║ ██║ ║ ║ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ║ ╚══════════════════════════════════════════════╝▸ Production-grade autonomous AI agent workspace
▸ Sandboxed file operations · Shell execution · Web search
▸ Powered by OpenRouter / Groq / NVIDIA NIM
▸ Runtime: Python 3.14 + FastAPI · React 19 + Vite 7
▸ Sandbox: Novita
Overview
OpenCurro (also known as Novita Agent Studio) is a full-stack web application that runs an autonomous AI coding agent inside an isolated Novita sandbox. The agent can read, write, and edit files, execute shell commands, search the web, fetch URLs, and delegate complex tasks to specialized sub-agents — all through a polished real-time chat interface.
🚀 Try it: Configure API keys → Select a model → Start building.
✨ Features
🧠 Agent Capabilities
|
🖥️ Frontend Experience
|
🔧 Backend Architecture
|
🔌 Extensible Design
|
🏗️ Architecture
graph TB
subgraph Browser["Browser (Frontend)"]
REACT["React 19 + TypeScript<br/>Vite 7 + Tailwind v4"]
ZUSTAND["Zustand 5 Store<br/>(Local Storage persistence)"]
SSE["SSE Client<br/>(ReadableStream)"]
UI["shadcn/ui Components<br/>Chat · Files · Settings"]
end
subgraph Backend["Python Backend (FastAPI)"]
API["API Routes<br/>/api/chat · /api/providers · /api/sandbox"]
AGENT["AgentRunner<br/>Main Agent Loop"]
TOOLS["ToolRegistry<br/>9 Tools"]
PROVIDERS["ProviderRegistry<br/>OpenRouter · Groq · NVIDIA"]
SANDBOX["SandboxRegistry<br/>Novita"]
SESSION["SessionStore<br/>(In-Memory)"]
SUBAGENTS["Sub-Agents<br/>DeepExplorer · DeepResearcher"]
end
subgraph External["External Services"]
LLM["LLM APIs<br/>OpenRouter / Groq / NVIDIA NIM"]
NOVITA["Novita Sandbox<br/>(Isolated Environment)"]
TAVILY["Tavily<br/>Web Search"]
FIRECRAWL["Firecrawl<br/>Web Fetch"]
end
BROWSER["Browser"] -->|"HTTP / SSE"| API
API --> AGENT
AGENT --> TOOLS
AGENT --> PROVIDERS
AGENT --> SANDBOX
AGENT --> SESSION
AGENT --> SUBAGENTS
PROVIDERS -->|"API Calls"| LLM
SANDBOX -->|"SDK"| NOVITA
TOOLS -->|"web_search"| TAVILY
TOOLS -->|"fatch_web_urls"| FIRECRAWL
TOOLS --> SANDBOX
classDef frontend fill:#f0f9ff,stroke:#3b82f6,stroke-width:2px
classDef backend fill:#f0fdf4,stroke:#22c55e,stroke-width:2px
classDef external fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
class REACT,ZUSTAND,SSE,UI frontend
class API,AGENT,TOOLS,PROVIDERS,SANDBOX,SESSION,SUBAGENTS backend
class LLM,NOVITA,TAVILY,FIRECRAWL external
linkStyle default stroke-width:2px
Data Flow
sequenceDiagram
participant U as User
participant F as Frontend
participant B as Backend API
participant A as AgentRunner
participant P as LLM Provider
participant S as Sandbox
U->>F: Send message
F->>F: Add user message to store
F->>B: POST /api/chat/stream (SSE)
B->>A: stream_turn()
A->>S: Create/get sandbox
S-->>A: Sandbox context
loop Agent Loop (max 1000 iterations)
A->>P: stream_chat_completion()
P-->>A: tokens / tool_calls
A-->>F: SSE: token, reasoning
alt has tool_calls
loop each tool_call
A-->>F: SSE: tool_call
A->>A: Execute tool
alt sub_agent called
A->>S: Sub-agent operations
S-->>A: Sub-agent events
A-->>F: SSE: subagent_*
end
A->>S: Sandbox operation
S-->>A: Result
A-->>F: SSE: tool_result
end
else no tool_calls
A-->>F: SSE: message_complete
A-->>F: SSE: done
Note over A: Exit loop
end
end
alt iteration limit
A-->>F: SSE: error
A-->>F: SSE: done
end
F->>U: Display final message
🧰 Tools
The agent has access to 9 tools for autonomous work:
| Tool | Purpose |
|---|---|
file_read |
Read file content from the sandbox |
file_write |
Create or overwrite files in the sandbox |
str_replace |
Exact string replacement (precise edits) |
list_files |
List directory contents |
shall_tool |
Execute shell commands (blocking or background) |
shell_view |
View output of background commands |
web_search |
Web search via Tavily API |
fatch_web_urls |
Fetch web page content via Firecrawl |
call_sub_agent |
Delegate task to a specialized sub-agent |
🤖 Sub-Agents
| Agent | Purpose | Allowed Tools |
|---|---|---|
| DeepExplorer | Read-only code exploration | list_files, file_read |
| DeepResearcher | Web research with file output | web_search, fatch_web_urls, file_write, list_files, shall_tool |
Sub-agents run in their own mini agent loops with restricted tool sets, communicating results back via asyncio.Queue.
🚀 Getting Started
Prerequisites
- Python 3.14+
- Node.js 20+
- API keys for: LLM provider (OpenRouter/Groq/NVIDIA), Novita sandbox, and optionally Tavily/Firecrawl
Development Setup
# 1. Clone the repository
git clone https://github.com/your-org/opencurro.git
cd opencurro
# 2. Start backend
cd backend
pip install -r requirements.txt
uvicorn src.main:app --reload --port 8000
# 3. Start frontend (in another terminal)
cd frontend
npm install
npm run dev
The frontend dev server proxies /api to localhost:8000 via Vite.
Production (Docker)
docker build -t opencurro .
docker run -p 8000:8000 opencurro
📁 Project Structure
opencurro/
├── backend/ # Python FastAPI backend
│ ├── src/
│ │ ├── main.py # App entry point
│ │ ├── core/config.py # pydantic-settings
│ │ ├── schemas/ # Pydantic models
│ │ ├── api/ # Router factories
│ │ ├── services/ # Session store
│ │ ├── agents/
│ │ │ ├── agent.py # AgentRunner loop
│ │ │ ├── providers/ # LLM providers (OpenAI-compatible)
│ │ │ ├── sandbox/ # Sandbox adapter (Novita)
│ │ │ ├── tools/ # 9 tool implementations
│ │ │ ├── subagents/ # DeepExplorer + DeepResearcher
│ │ │ └── systemprompts/ # System prompt
│ │ └── tests/ # pytest
│ └── requirements.txt
├── frontend/ # React + Vite + TypeScript
│ ├── src/
│ │ ├── App.tsx # Root layout
│ │ ├── components/chat/ # Chat UI
│ │ ├── components/files/ # File explorer
│ │ ├── components/settings/ # Settings modal
│ │ ├── store/ # Zustand stores (persisted)
│ │ ├── hooks/ # useAgentChat, useProviders
│ │ ├── lib/ # API client, env, utils
│ │ └── types/ # TypeScript interfaces
│ └── package.json
├── Dockerfile # Multi-stage production build
├── Dockerfile.base # Pre-built base image
├── start.sh / stop.sh # Dev scripts
└── specs/ # Design specifications
🔌 API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Health check |
| GET | /api/providers |
List supported LLM providers |
| POST | /api/providers/models |
Fetch models for a provider |
| POST | /api/chat/session |
Create or hydrate a chat session |
| POST | /api/chat/stream |
Send message and stream SSE response |
| GET | /api/sandbox/files |
List sandbox file tree |
| GET | /api/sandbox/file-content |
Read sandbox file content |
| POST | /api/sandbox/file-content |
Write sandbox file content |
SSE Event Protocol
| Event | Direction | Description |
|---|---|---|
status |
Backend → Frontend | Lifecycle status updates |
iteration |
Backend → Frontend | Current iteration / limit |
sandbox |
Backend → Frontend | Sandbox created info |
token |
Backend → Frontend | LLM response token |
reasoning |
Backend → Frontend | LLM reasoning token |
tool_call |
Backend → Frontend | Tool being invoked |
tool_result |
Backend → Frontend | Tool execution result |
subagent_* |
Backend → Frontend | Sub-agent lifecycle events |
message_complete |
Backend → Frontend | Final assembled response |
error |
Backend → Frontend | Error occurred |
done |
Backend → Frontend | Turn complete |
🧪 Testing
cd backend
pytest src/tests/ -v
🔧 Configuration
Configuration is handled via environment variables (see backend/src/core/config.py):
| Variable | Default | Description |
|---|---|---|
APP_NAME |
Novita Agent Studio API |
Application name |
API_PREFIX |
/api |
API route prefix |
CORS_ORIGINS |
["*"] |
Allowed CORS origins |
MAX_ITERATION_LIMIT |
1000 |
Max agent loop iterations |
SANDBOX_ROOT_PATH |
/home/user |
Sandbox filesystem root |
DEFAULT_SANDBOX_TIMEOUT |
3600 |
Sandbox idle timeout (seconds) |
TAVILY_API_KEY |
"" |
Tavily web search key |
FIRECRAWL_API_KEY |
"" |
Firecrawl web fetch key |
🧱 Key Design Decisions
- No database — All persistence is browser Local Storage via Zustand
persistmiddleware; backend sessions are in-memory - Registry pattern — Providers, sandbox adapters, tools, and sub-agents all self-register
- Protocol-based abstraction —
LLMProviderandSandboxAdapterare Python Protocols for strong typing without coupling - SSE streaming — Agent loop yields structured events via async generator; frontend parses with
ReadableStream - DI via factory functions — API routers receive dependencies explicitly, wired in
main.py - Structured error handling — Tools return
ToolExecutionResult(ok=True/False)instead of raising exceptions - Path safety — All sandbox paths normalized and validated under
/home/user/
🧩 Tech Stack
Backend
| Technology | Purpose |
|---|---|
| Python 3.14 | Runtime |
| FastAPI | Web framework (REST + SSE) |
| Uvicorn | ASGI server |
| Pydantic / pydantic-settings | Schema validation |
| httpx | Async HTTP client |
| novita-sandbox | Sandbox Python SDK |
| tavily-python | Web search API |
| firecrawl-py | Web fetch API |
| pytest / pytest-asyncio | Testing |
Frontend
| Technology | Purpose |
|---|---|
| React 19 | UI framework |
| TypeScript 5.8 | Language |
| Vite 7 | Build tool |
| Zustand 5 | State management (with persistence) |
| Tailwind CSS v4 | Utility-first CSS |
| shadcn/ui (New York) | Component system |
| lucide-react | Icons |
| class-variance-authority | Component variants |
📜 License
MIT
Built with ❤️ by the OpenCurro team
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found