Zapcode: AI 에이전트를 위한 Rust의 TypeScript 해석기(2μs 시작, 샌드박스)
hackernews
|
|
📰 뉴스
#ai 딜
#ai 에이전트
#anthropic
#openai
#rust
#typescript
#샌드박스
#코드 실행
원문 출처: hackernews · Genesis Park에서 요약 및 분석
요약
Zapcode는 AI 에이전트가 코드를 통해 복잡한 로직을 처리할 수 있도록 돕는 Rust 기반 TypeScript 인터프리터입니다. 기존 Docker나 V8 방식대비 2마이크로초라는 빠른 시작 속도와 언어 수준의 보안 샌드박스를 제공하며, 실행 상태를 스냅샷으로 저장해 나중에 다시 이어서 실행(resume)할 수 있는 기능을 특징으로 합니다. Node.js 의존성 없이 단일 라이브러리로 임베디드가 가능하여 다양한 언어와 환경에서 AI가 생성한 코드를 안전하게 즉시 실행할 수 있습니다.
본문
Run AI-generated code. Safely. Instantly. A minimal, secure TypeScript interpreter written in Rust for use by AI agents Experimental — Zapcode is under active development. APIs may change. AI agents are more capable when they write code instead of chaining tool calls. Code gives agents loops, conditionals, variables, and composition — things that tool chains simulate poorly. - Codemode from Cloudflare - Programmatic Tool Calling from Anthropic - Code Execution with MCP from Anthropic - Smol Agents from Hugging Face But running AI-generated code is dangerous and slow. Docker adds 200-500ms of cold-start latency and requires a container runtime. V8 isolates bring ~20MB of binary and millisecond startup. Neither supports snapshotting execution mid-function. Zapcode takes a different approach: a purpose-built TypeScript interpreter that starts in 2 microseconds, enforces a security sandbox at the language level, and can snapshot execution state to bytes for later resumption — all in a single, embeddable library with zero dependencies on Node.js or V8. Inspired by Monty, Pydantic's Python subset interpreter that takes the same approach for Python. | Language completeness | Security | Startup | Snapshots | Setup | | |---|---|---|---|---|---| | Zapcode | TypeScript subset | Language-level sandbox | ~2 µs | Built-in, sum + i.price * i.qty, 0); ({ total, names: items.map(i => i.name) }) `); console.log(processor.run().output); // { total: 127.96, names: ["Widget", "Gadget"] } // External function (snapshot/resume) const app = new Zapcode(`const data = await fetch(url); data`, { inputs: ['url'], externalFunctions: ['fetch'], }); const state = app.start({ url: 'https://api.example.com' }); if (!state.completed) { console.log(state.functionName); // "fetch" const snapshot = ZapcodeSnapshotHandle.load(state.snapshot); const final_ = snapshot.resume({ status: 'ok' }); console.log(final_.output); // { status: "ok" } } See examples/typescript/basic/main.ts for more. from zapcode import Zapcode, ZapcodeSnapshot # Simple expression b = Zapcode("1 + 2 * 3") print(b.run()["output"]) # 7 # With inputs b = Zapcode( '`Hello, ${name}!`', inputs=["name"], ) print(b.run({"name": "Zapcode"})["output"]) # "Hello, Zapcode!" # External function (snapshot/resume) b = Zapcode( "const w = await getWeather(city); `${city}: ${w.temp}°C`", inputs=["city"], external_functions=["getWeather"], ) state = b.start({"city": "London"}) if state.get("suspended"): result = state["snapshot"].resume({"condition": "Cloudy", "temp": 12}) print(result["output"]) # "London: 12°C" # Snapshot persistence state = b.start({"city": "Tokyo"}) if state.get("suspended"): bytes_ = state["snapshot"].dump() # serialize to bytes restored = ZapcodeSnapshot.load(bytes_) # load from bytes result = restored.resume({"condition": "Clear", "temp": 26}) See examples/python/basic/main.py for more. Rust use zapcode_core::{ZapcodeRun, Value, ResourceLimits, VmState}; // Simple expression let runner = ZapcodeRun::new( "1 + 2 * 3".to_string(), vec![], vec![], ResourceLimits::default(), )?; assert_eq!(runner.run_simple()?, Value::Int(7)); // With inputs and external functions (snapshot/resume) let runner = ZapcodeRun::new( r#"const weather = await getWeather(city); `${city}: ${weather.condition}, ${weather.temp}°C`"#.to_string(), vec!["city".to_string()], vec!["getWeather".to_string()], ResourceLimits::default(), )?; let state = runner.start(vec![ ("city".to_string(), Value::String("London".into())), ])?; if let VmState::Suspended { snapshot, .. } = state { let weather = Value::Object(indexmap::indexmap! { "condition".into() => Value::String("Cloudy".into()), "temp".into() => Value::Int(12), }); let final_state = snapshot.resume(weather)?; // VmState::Complete("London: Cloudy, 12°C") } See examples/rust/basic/basic.rs for more. WebAssembly (browser) import init, { Zapcode } from './zapcode-wasm/zapcode_wasm.js'; await init(); const b = new Zapcode(` const items = [10, 20, 30]; items.map(x => x * 2).reduce((a, b) => a + b, 0) `); const result = b.run(); console.log(result.output); // 120 See examples/wasm/basic/index.html for a full playground. npm install @unchartedfr/zapcode-ai ai @ai-sdk/anthropic # or @ai-sdk/amazon-bedrock, @ai-sdk/openai The recommended way — one call gives you { system, tools } that plug directly into generateText / streamText : import { zapcode } from "@unchartedfr/zapcode-ai"; import { generateText } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; const { system, tools } = zapcode({ system: "You are a helpful travel assistant.", tools: { getWeather: { description: "Get current weather for a city", parameters: { city: { type: "string", description: "City name" } }, execute: async ({ city }) => { const res = await fetch(`https://api.weather.com/${city}`); return res.json(); }, }, searchFlights: { description: "Search flights between two cities", parameters: { from: { type: "string" }, to: { type: "string" }, date: { type: "string" }, }, execute: async
Genesis Park 편집팀이 AI를 활용하여 작성한 분석입니다. 원문은 출처 링크를 통해 확인할 수 있습니다.
공유