remote-compute-modal
Run GPU jobs on the user's own Modal account via host.compute.create('byoc:modal', ...). Covers the create→submit→wait_for_notification flow, the compute_provider kernel for env setup, image/volume resolution, and the two approval cards. Load once you've decided to dispatch to Modal.
git clone --depth 1 https://github.com/UnicomAI/wanwu /tmp/remote-compute-modal && cp -r /tmp/remote-compute-modal/configs/microservice/bff-service/configs/agent-skills/claude-science/remote-compute-modal ~/.claude/skills/remote-compute-modalSKILL.md
You're dispatching to the user's Modal account: containers spin up in Modal's
cloud, on hardware you name in plain terms (gpu/cpu/memory/timeout), under
their workspace, on their bill. That's the reason there are
two approval cards rather than one, and the reason the env-setup surface is
a separate kernel rather than something you can call inline from the
control-plane kernel: each card is the user consenting to a specific,
bounded use of their credential, and the architecture keeps those grants
legible by keeping the surfaces apart.
If `compute.create('byoc:modal', …)` returns `unknown provider 'byoc:modal'`,
Modal isn't enabled in this install — ask the user to enable it under
*Settings → Compute → Modal* (or surface the prompt; you can't enable it for
them).
For first-time environment setup, see `env-setup.md` in this skill
directory — it walks through driving the `compute_provider` kernel to
build and record images.
## Two timeouts, one timeline
Modal has two deadline timers. Both live INSIDE the sandbox, and neither
can cost you the outputs of a job that ran. The timeline every job runs
on:
1. Container life starts at sandbox creation — staging the inputs counts
against it, so a big upload spends container time before the job runs.
2. The job runs. If it exceeds its own budget (the job timeout below), it
is TERMed there.
3. Near end of container life — one harvest margin before the provider
destroys the sandbox — the in-sandbox **harvest watchdog** TERMs
whatever is still running. It runs on the sandbox's own clock, so a
wrong desktop clock or a slow upload can't make it fire late.
4. After any TERM there is a grace window for checkpoint-on-TERM handlers
to flush, then the process group is stopped.
5. Whatever is under `./out/` (plus the logs) is tarred and staged
UNCONDITIONALLY — on success, timeout, failure, and crash alike — and
harvested back into the workspace. Staging is unconditional; delivery
isn't. If the stream is refused or gives up (`result_rejected`,
`harvest_failed`), the staged copy waits on the sandbox, and a third,
post-job timer — the **idle watchdog** — terminates it after ~30 min
of inactivity. See "When the job fails".
The **container timeout** (`provider_params.modal.timeout`) is how long
the sandbox lives; omitted, it fills from the Settings default for this
provider (*Settings → Compute → Modal*; ceiling: Modal's 24 h platform
lifetime, minus the staging margins — 85,500 s). The **job timeout**
(`timeout_seconds` on `submit_job`) is an optional runaway guard for one
job; omitted, it defaults to the container's remaining life minus the
harvest margin. Name one when you know the job's budget — a hung job then
costs that budget, not the whole container, and the warm container
survives for the next submit.
A deadline-ended job lands as `status: 'timed_out'` — not a generic
failure — with its partial outputs already harvested, plus a note saying
the deadline (not the workload) ended the run and suggesting the remedy:
a larger `timeout_seconds`, or resuming from a harvested checkpoint. A
deadline ends the run, never the results.
## Two surfaces, one provider
You reach Modal two ways. They share confinement and credentials but answer
different questions, and confusing them is the most common way to waste a
turn.
`host.compute.create('byoc:modal', provider_params={'modal': {...}})` is
the **job surface**. It runs in the `repl` tool — same as
`remote-compute-ssh` — and is what you use for anything with
inputs/outputs you want harvested into the workspace, anything on a GPU, and
anything long enough that you'd want to reattach if the daemon restarts. The
call itself is a stateless constructor — the **tier card** (provider, image,
`1× A100-40GB · 8 CPU · 32 GB`, container timeout, volumes) and the actual
Sandbox creation both happen on the first `submit_job()`.
`submit_job`/`result`/`call_command`/`attach_job`/`close` then work exactly
as for SSH: `.result()` is **non-blocking** — the daemon's poller probes the
sandbox, harvests `out.tar.gz` into `hpc/<jobId>/`, and emits a
`compute_done` notification when done. To wait, exit the cell after
`submit_job` and use the `wait_for_notification` brain-tool. What reaches
the remote is what was in the workspace files you named, and what comes
back lands under `hpc/<jobId>/` through the same hardened extractor.
`compute_provider({'provider': 'modal', 'code': '…'})` is the **environment
surface** — a Python shell with the user's Modal SDK already authenticated,
running in its own confined process. Use it to *prepare* compute: build
container images JIT in the user's workspace, populate model-weight volumes
by running the downloads on Modal's own infrastructure (so wide-internet
fetches never traverse the local allowlist), check what assets already
exist, run a short CPU smoke probe. Its first cell in a session fires the
**kernel card** — *"environment setup — build images, populate volumes, CPU
probes ≤30 min; GPU jobs ask separately"* — and once granted, subsequent
cells in this kernel's lifetime (idle-timeout ~15 min) run without further
prompts. The kernel will reject `gpu=` on `Sandbox.create` and clamp
`timeout` to ≤30 min — the kernel's own probe budget, separate from the
job surface's container timeout. It's a redirect to the job surface, not
a fence; you've already been handed the credential. **Terminate every
sandbox you create here** — `sb.terminate()` in the same cell, in a
`try/finally` if you `exec` in between (`build_env`'s hydrate models
this). Nothing reaps it mid-session: the idle timeout kills the
*kernel*, never your sandboxes — the ≤30-min clamp only bounds how long
a forgotten one bills.
The shape of a good run is: read what's already known about this workspace,
decide whether the env you need exists, build it via the `compute_provider`
kernel if it doesn't, then run the actual job through `compute.create()`.
The two cards appear at most once each per session —Headless browser automation CLI optimized for AI agents with accessibility tree snapshots and ref-based element selection
万悟平台 SSE 子会话递归嵌套与三明治序列渲染架构指南。涵盖 parentId 领养、order 绝对排序、动静 Chunk 分层及 Vue 2 响应式引用协议。
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
>
全局归档协议。只要任务需要写入任何文件(含 PLAN.md、报告、JSON 等归档物),必须按本技能执行 Session→ARCHIVE_ID、TIMESTAMP、双轨路径(根段须为 archives/)、回读校验与状态回执;WebUI 的 archive_grid 必须用 Markdown 中语言标识为 json 的围栏代码块输出。
>-
指导业务知识网络(BKN)建模,输出符合 BKN 2.0.0 的对象类型、关系类型、操作类型、风险类型与概念分组定义。适用于用户提出本体设计、知识网络建模、实体关系梳理、Action 设计、Schema 评审、从文档提取初稿或扩展现有 BKN 的场景。
>