Autonomy
The 1.8 primitives for fully autonomous, self-verifying agents — workspace memory, CodeAct code execution, planner/executor/verifier loops, parallel fan-out, browser control, and background runs. Edge-safe core, Node-only reference adapters.
Текст страниц документации на английском. Навигация, поиск и интерфейс следуют выбранному языку.
Deuz 1.8 adds the primitives to build a Manus-style autonomous system — a run that plans, acts by writing and executing code, verifies itself, and keeps working across restarts — without giving up the zero-dependency, lint-guaranteed edge-safe core. Every heavy capability is a seam with a Node-only reference adapter, so you plug in Docker/E2B/Playwright and the core stays pure. There is no agent class: you compose free functions.
Workspace — externalized memory
An autonomous run needs a place to keep plan.json, notes, and artifacts so progress survives compaction, a durable checkpoint, or a full restart. That is the Workspace seam.
import { createInMemoryWorkspace, createWorkspaceTools } from '@deuz-sdk/core/workspace';
import { createFileWorkspace } from '@deuz-sdk/core/workspace/node'; // sandboxed directory
const workspace = createFileWorkspace({ root: './.agent-workspace' });
await workspace.write('plan.json', '{}');
// Expose it to the model as tools (readFile / writeFile / listFiles / deleteFile).
const tools = createWorkspaceTools(workspace, { approveWrites: true });Paths are normalized and traversal (.., absolute paths) is rejected before the backend ever sees them. Back the seam with any KV/object store (S3, R2, a DB table) in a few lines.
Only a whole .. segment is traversal: ..notes or ... are ordinary names. An illegal path rejects from every method, exists and delete included; a missing path is the only soft case (exists → false, delete → no-op). createFileWorkspace also re-checks the real path, so a symlink or NTFS junction inside the root cannot lead a read or write outside it, and a write never goes through a link that does not resolve.
Compute / CodeAct — action as executable code
The reliable way to make an agent act (instead of describing what it would do) is to let it write code and run it. ComputeSandbox is the seam; codeActTool/shellTool wrap it as tools.
import { codeActTool, shellTool, codeActSystemPrompt } from '@deuz-sdk/core/compute';
import { createNodeSandbox } from '@deuz-sdk/core/compute/node';
const sandbox = createNodeSandbox({ allowedLanguages: ['python', 'bash', 'javascript'] });
const tools = {
...codeActTool(sandbox, { languages: ['python', 'bash'] }),
...shellTool(sandbox),
};A thrown run becomes a self-healing is_error result the loop feeds back, so the model can switch strategy (Python fails → shell) — the CodeAct self-correction loop.
runCode and runShell take an optional stdin, written as UTF-8 and then closed; without it the process reads EOF at once, so sort, cat or a script that reads stdin finishes instead of waiting out the timeout. There is no interactive input. A timeout or abort returns timedOut: true with exitCode: null. Since 2.4, createNodeSandbox kills the whole process tree (the process group on POSIX, taskkill /T /F on Windows), spawns children with windowsHide, and settles within about half a second of the kill even if a program that escaped the tree still holds the output.
runShell's cwd is confined to the sandbox root, options.cwd or else the host's working directory (2.4, a behaviour change): a relative path resolves against the root, and .., an absolute path elsewhere, a symlink or junction pointing out, or a missing directory is refused with exitCode: null and the reason in stderr, without running anything. When a stream passes maxOutputBytes, the result's truncated: { stdout, stderr } (2.4) says which one was cut.
createNodeSandboxis a reference, not a security sandbox — it runs code as a child process of the host. For untrusted input or production, backComputeSandboxwith real isolation.createDockerSandbox(2.4, preview) is the built-in option: local Linux containers with no network, a non-root user and resource limits. E2B, Daytona, Fly Machines or a microVM fit the same seam; only the backend changes. Approval gates whether a call runs, not what it can reach.
Planner → Executor → Verifier
planTasks decomposes a goal into an ordered TaskList you drive with pure reducers and persist as plan.json:
import { planTasks, nextPendingTask, setTaskStatus, taskListProgress } from '@deuz-sdk/core/autonomy';
let plan = await planTasks('Build and test a CLI', { model });
for (let task = nextPendingTask(plan); task; task = nextPendingTask(plan)) {
// …delegate task.title to an executor sub-agent…
plan = setTaskStatus(plan, task.id, 'done');
}The verifier is the verifyStep hook on any agentic call (both generateText and streamChat). It runs at every natural completion; a rejection feeds feedback back as a user turn and re-drives the loop, bounded by maxVerifyAttempts:
const result = await generateText({
model,
messages,
verifyStep: ({ text, attempt }) =>
text.includes('PASS') ? { ok: true } : { ok: false, feedback: 'Run the tests and paste the result.', retry: attempt < 2 },
});
result.providerMetadata?.deuz?.verified; // true | falseStreaming emits a verify part per evaluation. Verify retries are a separate budget from maxSteps; stopWhen/budget still bound the whole run.
Verified + parallel generation
import { bestOfN, selfConsistency, parallelAgents } from '@deuz-sdk/core/autonomy';
// Generate N candidates, score each, keep the best.
const { best } = await bestOfN({ n: 5, generate: () => draft(), score: (d) => rate(d) });
// Majority-vote N samples.
const { answer } = await selfConsistency({ n: 5, generate: () => solve() });
// "Wide Research": run many independent agents concurrently.
const { results } = await parallelAgents({ model, tasks: urls.map((u) => `Summarize ${u}`), concurrency: 10 });Browser control
import { createBrowserTools } from '@deuz-sdk/core/browser';
import { createPlaywrightBrowser } from '@deuz-sdk/core/browser/node'; // optional peer: playwright
const browser = createPlaywrightBrowser({ headless: true });
const tools = createBrowserTools(browser, { workspace, needsApproval: true });
// navigate / click / type / readText / screenshot (screenshots save to the workspace)Background runs + live view
RunStore tracks run metadata (status, plan snapshot) alongside the durable SessionStore checkpoints, so a dashboard can list runs and a worker can continue the ones whose process died.
import { createRunManager, createInMemoryRunStore, emitActivity, emitPlanUpdate } from '@deuz-sdk/core/runtime';
import { createFileRunStore, pollStaleRuns } from '@deuz-sdk/core/runtime/node';
const runs = createRunManager({ store: createFileRunStore({ dir: './.runs' }) });
await runs.startRun({ runId, goal });
// …drive the model with session: { store: sessionStore, runId } …
await runs.setStatus(runId, 'completed');
// A worker/cron continues crashed runs:
for (const stale of await pollStaleRuns(store, { staleMs: 60_000 })) {
// resumeFromCheckpoint(sessionStore, stale.runId, { model, tools, … })
}From inside a tool (streaming parent), feed the UI's to-do panel and "Computer" activity feed:
emitPlanUpdate(ctx.emitPart, plan); // → plan-update part
emitActivity(ctx.emitPart, 'opened pricing page', { level: 'info' }); // → activity partBoth parts flow through the UI wire, the chat engine, and useChat (plan / activity). Use createSteeringController + prepareStep to inject a mid-run user message ("actually, focus on X") at the next step boundary.
Providers + model router
Published OpenAI-compatible factories and a zero-network string router live at @deuz-sdk/core/providers:
import { createProviderRegistry, createGroq } from '@deuz-sdk/core/providers';
import { createOpenAI } from '@deuz-sdk/core/openai';
const registry = createProviderRegistry({
groq: createGroq({ apiKey: process.env.GROQ_API_KEY! }),
openai: createOpenAI({ apiKey: process.env.OPENAI_API_KEY! }),
});
const model = registry.model('groq:llama-4-maverick');Also exported: createMistral, createDeepSeek, createQwen, createKimi (alias of createMoonshot), createTogether, createOpenRouter, createCerebras, createFireworks, createGLM, createMiniMax, plus createAzure / createBedrock (also dedicated @deuz-sdk/core/azure and /bedrock). Full table: OpenAI-compat hosts.
Testing
Deterministic agent tests use the published @deuz-sdk/core/testing subpath (createMockModel, runEval, golden-replay fixtures) — no real network required.
For versioned eval tasks with per-attempt metrics (success, false completion, cost, duration, human rescues, repeated effects, recovery), use runEvalSuite from the same subpath (2.3). See Evals, which also covers the offline tasks and the fault-injection suite of the 2.3 baseline.
See also
- Build your own Manus — all of the above composed into one autonomous agent.
- Durable runtime — the checkpoint/resume layer background runs build on.
- Sub-agents —
agentTool, the executor in the loop. - Installation — subpaths — full export table including autonomy surfaces.
Retention and forget
The explicit cleanup calls of every 2.4 store, what each keeps so that deduplication and audits still hold, and how a versioned memory forget redacts the compiled context packages of V3 runs (2.4).
Docker runner
A local Docker sandbox for the compute tools and a process runner that reconnects after a host restart, with isolation defaults, a fixed start order, recorded cancels, checked artifacts and explicit cleanup (2.4, preview).