Skip to main content

Run tasks

Task submission supports local two-file directories or SDK file-content mappings. The SDK reads files and sends their contents; the remote machine does not need access to the client directory. Named Runner / Dataset submissions use the APIServer catalog; the platform downloads the problem when executing it.

Submit and inspect​

First prepare ./my-task and the connection configuration from Quickstart:

el task submit ./my-task --wait
el task status TRIAL_ID
el task snapshot TRIAL_ID
el task result TRIAL_ID
el task stop TRIAL_ID

Replace TRIAL_ID with the ID returned on submission. HTTP submission returns immediately by default; --wait explicitly waits. Local CLI submission waits for execution to end. result itself does not wait. The CLI has no task logs, task cancel, or task wait subcommands.

Harbor Runner​

After registering the Runner and Dataset in your APIServer catalog and configuring the connection, run the fix-git task:

el task submit \
--runner envhub/harbor@0.23.0 \
--dataset envloop/terminal-bench-2-1-lite@1.0.1 \
--task-id terminal-bench/fix-git \
--queue-id default \
--priority 10 \
--wait

The example pins Dataset version 1.0.1; the selected names and versions must exist in your catalog. It does not establish production catalog availability or a verified benchmark result.

No --command is needed: runner.toml declares main.sh, so the platform runs bash main.sh. A Python Runner declaring main.py similarly uses python main.py. Use --command only to customize startup. The Harbor Runner requires an execution node with Docker-in-Docker (DinD) support enabled.

Inline files with Python​

from envloop import Client

files = {
"runner.toml": '''schema_version = "envhub.runner/v1"
[runner]
name = "examples/inline"
version = "1"
[execution]
entrypoint = "main.py"
timeout_sec = 10
''',
"main.py": 'print("inline hello")\n',
}
with Client.remote() as client:
trial = client.tasks.submit(files, request_id="inline-hello-001")
final = client.tasks.wait(trial["trial_id"], timeout=60)
print(final["status"])
print(client.tasks.result(trial["trial_id"])["stdout"])

The first run should return succeeded, with stdout containing inline hello and a newline. Reusing the same request_id reuses the original Trial; use a new value to rerun intentionally.

Results and artifacts​

The result dictionary includes stdout, stderr, and outputs. Each output contains name, content, size, and sha256. Only artifacts declared by the task are returned as outputs; see Task format. SHA-256 covers raw bytes; content is decoded text and should not be re-encoded to verify arbitrary binary files.

Local logs remain in logs/trials/<trial_id>/ under the current directory at startup, including stdout.log, stderr.log, and manifest.json, independently of work_dir. Remote execution logs are not written to this client directory.

Timeout and cancellation​

tasks.wait(timeout=...) limits client waiting time; a TimeoutError does not cancel execution. execution.timeout_sec limits task execution time. Explicitly call tasks.stop() to stop; the backend may reject cancellation. For example, E2B currently returns CANCELLATION_UNSUPPORTED, which does not mean cloud resources have been reclaimed.

See Troubleshooting for error handling.