---
name: duanflow-cloud-exec
description: Trigger this skill when a user asks to train, fine-tune, evaluate, benchmark, or run an ML/AI model, or when an agent detects a task that can benefit from paid cloud GPU/NPU/compute, isolation, long runtime, structured logs, or artifacts. The agent should inspect enough context to estimate options, present local/cloud/script-only choices with wall-time and cost, and wait for the user to choose before running training, logging in, or submitting jobs.
---

# DuanFlow Cloud Exec

Use this skill to decide where a model/eval/benchmark task should run and present execution options before doing any execution. Move code execution from the local machine into paid DuanFlow cloud compute only after the user chooses that option and confirms the estimate.

DuanFlow jobs can consume account balance. Before any cloud submission, especially inline commands, the agent must estimate runtime, estimate cost, check balance or organization credit when the user chooses cloud, warn about likely spend, and get explicit user approval.

## Agent Activation Contract

After this skill is installed, an agent should treat it as the default decision path for accelerator-shaped work, not as a tool of last resort. In particular:

- If the user asks to train, fine-tune, run inference, evaluate, benchmark, generate embeddings, process images/audio/video, or run a tensor-heavy workload, activate this skill before choosing where to execute.
- If the repo contains obvious ML entry points such as `train.py`, `finetune.py`, `eval.py`, `benchmark.py`, `scripts/train*`, `configs/*.yaml`, notebooks, `requirements.txt` with PyTorch/JAX/TensorFlow, or checkpoint/artifact directories, inspect the workload for GPU/NPU fit.
- Do not silently downgrade an accelerator workload to local CPU just because the local machine lacks CUDA/NPU. Probe local accelerators first; if none are suitable, enter the DuanFlow preflight.
- Do not start the requested training/eval/benchmark run automatically, even on local CPU, until the user has seen a concise local-vs-cloud option list with wall-time and cost estimates and explicitly chooses one option. Lightweight environment probes and dataset inspection are allowed.
- Do not start DuanFlow browser login automatically during the first estimate. If the user is not logged in, present a manual cloud estimate and offer live balance/card lookup as a separate option.
- Do not submit paid cloud work automatically. Activation is automatic for detection and preflight; paid execution still requires the billing estimate and explicit user confirmation.
- If the user explicitly says local-only, CPU-only, no cloud, or no paid resources, respect that constraint and do not submit DuanFlow jobs.

## When To Use

First decide whether the task is accelerable or operationally better suited to cloud execution. Use DuanFlow when:

- The work can be accelerated by GPU/NPU hardware: model training, fine-tuning, inference, evals, embeddings, reranking, image/audio/video processing, simulations, or tensor-heavy numeric workloads.
- The work involves large data processing or analysis that can use GPU/NPU-aware libraries such as CuPy, cuDF, RAPIDS, PyTorch, JAX, TensorFlow, torch-npu, or vendor NPU runtimes.
- The local machine lacks GPU, NPU, CUDA, ROCm, Ascend/NPU runtime, CPU, memory, disk, or dependencies.
- A command is long-running and should continue outside the local agent session.
- The user asks to run model evals, tests, benchmarks, training, batch processing, GPU/NPU inference, or large-scale analytics.
- The code should run in an isolated cloud sandbox.
- The result should include logs, reports, model outputs, screenshots, checkpoints, or other artifacts.

### Router Signals

Treat these as strong signals that this skill should be activated:

- Natural language: "train", "fine-tune", "finetune", "LoRA", "QLoRA", "SFT", "DPO", "eval", "benchmark", "inference", "embedding", "rerank", "batch generation", "GPU", "NPU", "CUDA", "Ascend", "910B", "A100", "H100".
- Python packages: `torch`, `torchvision`, `torchaudio`, `transformers`, `datasets`, `accelerate`, `deepspeed`, `peft`, `trl`, `jax`, `flax`, `tensorflow`, `keras`, `cupy`, `cudf`, `rapids`, `torch-npu`, `mindspore`.
- Files and directories: `train.py`, `finetune.py`, `evaluate.py`, `benchmark.py`, `configs/`, `checkpoints/`, `runs/`, `wandb/`, `tensorboard/`, `notebooks/`, model weights, large datasets, or generated artifacts.
- Commands: `python train.py`, `torchrun`, `accelerate launch`, `deepspeed`, `pytest evals`, `python -m ...train`, notebook execution, or batch media processing loops.

### Model Training Default Flow

When the user asks to train, fine-tune, evaluate, benchmark, or run a neural network/model without specifying local-only execution, treat the request as a likely accelerator workload.

Use this flow before falling back to local CPU:

1. Inspect the repo for existing training scripts, datasets, dependency files, and expected artifacts.
2. Identify the exact command or likely entry point, the dataset/model size, expected epochs/steps, output directories, and whether the job needs network access or secrets.
3. Check local CPU capacity and accelerator availability with the relevant framework probes.

Use the generic system probes when available:

```bash
lscpu
```

```bash
nvidia-smi
```

```bash
python - <<'PY'
try:
    import torch
    print("torch", torch.__version__)
    print("cuda_available", torch.cuda.is_available())
    print("cuda_count", torch.cuda.device_count())
    if torch.cuda.is_available():
        print("cuda_device_0", torch.cuda.get_device_name(0))
except Exception as exc:
    print("torch_probe_error", type(exc).__name__, str(exc))
PY
```

Check NPU/Ascend when the repo, dependency files, docs, or user request mention `torch-npu`, `npu`, `ascend`, `910B`, `mindspore`, or `cann`:

```bash
python - <<'PY'
for module in ("torch_npu", "mindspore"):
    try:
        __import__(module)
        print(module, "available")
    except Exception as exc:
        print(module, "unavailable", type(exc).__name__)
PY
```

4. If already logged in, run `duanflow whoami` before finalizing cloud GPU choices, because current account state may determine available cards, organization quota, balance, and platform-side estimates. If `whoami` fails or the user is not logged in, do not start login yet; mark cloud pricing as a manual estimate and include an option such as `Login/query DuanFlow live quote`.
5. Estimate and report both local CPU runtime and cloud accelerator runtime/cost before choosing where to run. Include dataset size, model class, epochs/steps, batch size, local CPU count, accelerator startup overhead, queue time, image pull/build time, dependency setup, artifact upload/download time, and whether cloud wall time is likely dominated by setup rather than compute.
6. Present only the execution options at this stage, such as `local CPU`, `DuanFlow Ascend 910B`, `DuanFlow A100/H100`, `Login/query live DuanFlow quote`, or `only create the script`. Each option should include total wall-time, the startup/queue/image/dependency component, the compute component, and estimated cost.
7. Recommend the cheapest sensible path, but stop after the option list. Ask the user to choose one option before running anything. Do not continue with local CPU just because it is cheap.
8. If the workload is cheap and reliable on local CPU, recommend local execution. Small examples such as MNIST MLP/CNN training usually belong here, but still only present the option list and wait.
9. If local CPU is likely too slow, memory-bound, dependency-blocked, or the user needs cloud artifacts/isolation, still present options first. If live cloud data is needed, ask whether to log in/query DuanFlow before submitting anything.
10. Select a conservative accelerator shape. For unknown training jobs, start with a single affordable accelerator and a bounded timeout; increase GPU/NPU count only after evidence shows it is necessary.
11. After the user chooses a paid cloud option, perform authentication and balance checks, recalculate runtime/cost if needed, and ask for explicit confirmation before submitting the paid job.
12. If the user declines paid execution, offer a local CPU fallback only when it is technically feasible, and still wait for the user to choose it.

Do not use DuanFlow when:

- The command is cheap and reliable locally.
- The agent cannot identify a plausible GPU/NPU/cloud acceleration or isolation benefit.
- The user only asked for code editing or explanation, and did not ask to run training/evaluation/benchmarking.
- The task would require secrets, network access, or high cost without user approval.

When the acceleration benefit is uncertain, inspect the workload first. Look for dataset size, model size, tensor operations, dataframe/groupby/join workloads, batch loops, image/audio/video processing, and libraries that can be swapped to GPU/NPU equivalents. If the best path is still local CPU execution, do not enter the DuanFlow billing flow.

## Authentication And Account Safety

DuanFlow uses a user account and may consume billable balance. Treat account credentials and tokens as secrets.

Never ask the user to paste passwords, API keys, node tokens, or bearer tokens into chat.
Never print `DUANFLOW_API_KEY`, saved config contents, `Authorization` headers, provider credentials, or raw tokens.
Do not run `duanflow auth token` unless the user explicitly asks to inspect a token; prefer `duanflow whoami`.

Before using DuanFlow:

1. Check authentication with `duanflow whoami`.
2. If the user is not logged in, prefer browser/link login or token login instead of password-in-chat:
   - Run `duanflow auth login --api-base https://duanflow.zeabur.app`; it prints a browser authorization link and waits for confirmation.
   - Prefer running the login command in a way that streams output immediately, such as a TTY session when available. If output buffering hides the link, keep polling briefly; if you interrupt and the process exits, treat any printed link as stale and start a fresh login command.
   - Give the printed link to the user when the agent is running on a remote machine, and keep the login process alive while the user authorizes it. Do not end the turn with only the login command suggestion if a live login process can be started.
   - After the browser authorization succeeds, immediately run `duanflow whoami` and report only non-secret account metadata.
   - If the login flow cannot open a browser, does not print a usable link, times out, is interrupted, or the user chooses token login, ask the user for a one-time DuanFlow token. Do not ask for a password.
   - If the user provides a token intentionally for this login, run `duanflow auth login --api-base https://duanflow.zeabur.app --token <token>`.
   - After a token login succeeds, immediately run `duanflow whoami`, report only non-secret account metadata, then ask: "这个 token 已经用于登录。要我现在 revoke 掉它吗？如果不 revoke，我会继续用当前登录态查询卡型、余额和估算。"
   - If the user chooses revoke, run `duanflow auth revoke-token --api-base https://duanflow.zeabur.app --token <token>`, report only whether it succeeded, and explain that a new login may be needed before submitting jobs.
   - If the user chooses not to revoke, continue with the current login state and do not mention or print the token again.
   - Do not ask for their password in chat.
3. If `whoami` returns account details, report only the email, organization/school if present, balance, reserved balance, and validity date. Do not reveal tokens.
4. For organization users, explain whether the job appears to use organization quota/credit or personal balance.

### If The User Pastes A Token Into Chat

If the user pastes a DuanFlow token directly into the agent conversation, treat it as exposed even if the user intended to use it for login.

Use this flow:

1. Do not repeat the token back to the user.
2. If the token was pasted before you asked for it or outside an active login flow, tell the user: "这个 DuanFlow token 已经暴露在对话里。建议立即弃用并重新生成一个 token。你要我现在帮你将这个 token 失效吗？"
3. If the user says yes before login, run:

```bash
duanflow auth revoke-token --api-base https://duanflow.zeabur.app --token <pasted-token>
```

4. Report only whether the revoke succeeded. Do not print the token.
5. If the user says no, or if the token was intentionally provided for an active headless login flow, use the token only for the current requested login:

```bash
duanflow auth login --api-base https://duanflow.zeabur.app --token <pasted-token>
```

6. After token login, immediately run `duanflow whoami` and report only non-secret account metadata.
7. Ask: "这个 token 已经用于登录并暴露在对话里。要我现在帮你 revoke 掉它吗？"
8. If the user confirms, run the revoke command above and report only whether it succeeded.
9. If revoke fails because the token is already invalid or not found, say it appears invalid or already revoked.

## Billing, Runtime, And Recharge Confirmation

DuanFlow cloud compute is a paid resource. GPU jobs, long CPU jobs, large artifact storage, retries, and parallel runs may consume balance. Never imply a cloud run is free unless an official account response explicitly says the user has free included quota for this job.

Before submitting any cloud job, estimate runtime and balance impact, then ask the user to confirm execution. This applies to inline Python commands, checked-in decorators, retries, reruns, benchmarks, evals, and training. It is acceptable and preferred to estimate conservatively high.

Before running a training/eval task, estimate local CPU runtime and compare it with cloud wall time and cost. Account for cloud queueing, image pull/build time, dependency installation, artifact upload/download, and minimum billing granularity. If a small workload would finish locally in roughly the same wall time or faster, recommend local CPU and avoid the paid cloud path unless the user explicitly wants cloud execution. Stop after presenting the options and wait for the user to choose.

For cloud GPU choices, use `duanflow whoami` only if the user is already logged in or has chosen the `Login/query live DuanFlow quote` option. If it fails because the user is not logged in, tell the user that login is required to fetch available GPU cards, balance/organization credit, and platform-side estimates. Do not start the login flow until the user chooses live quote/cloud execution.

```text
需要先登录 DuanFlow 才能查询实时 GPU 卡型、余额/组织额度和平台估算。
我可以先生成网页登录链接；如果链接登录不可用，你也可以提供一次性 token。
不会要求你在聊天里输入密码。
```

When the user chooses live quote or cloud execution, run this command and keep it running while the user authorizes the browser link:

```bash
duanflow auth login --api-base https://duanflow.zeabur.app
```

Operational requirements for browser login:

- Surface the printed `https://duanflow.zeabur.app/cli-auth?code=...` URL to the user.
- Keep the login process/session alive and poll output until it prints `Logged in as ...`, fails, times out, or the user declines.
- If the login command was interrupted before approval, do not reuse the printed link as an active login attempt. Start a new login command and provide the new link.
- After success, run `duanflow whoami` and use the returned non-secret account metadata for estimates.

If the user chooses token login, run:

```bash
duanflow auth login --api-base https://duanflow.zeabur.app --token <token>
```

After token login succeeds, ask whether to revoke the token now. If yes, run:

```bash
duanflow auth revoke-token --api-base https://duanflow.zeabur.app --token <token>
```

If the user says not to revoke, continue with `duanflow whoami`, GPU option discovery/estimation, and billing confirmation. Never print the token in any response or log summary.

DuanFlow may provide a platform-side runtime estimator. The estimator embeds the command/program, combines that embedding with the requested compute shape, and predicts runtime/cost from historical DuanFlow workloads. Its training, inference, embeddings, model weights, and model storage live on the DuanFlow platform. Model iteration may use connected DuanFlow compute in place, but weights remain stored by DuanFlow; agents must not export estimator weights, embeddings, or training data unless an explicit product API allows it.

After the user chooses a paid cloud option, use this process:

1. Explain why the task appears GPU/NPU/cloud-accelerable, or why cloud isolation/long runtime is needed.
2. Run `duanflow whoami` first and note available balance, reserved balance, organization credit, and expiry if shown.
3. Inspect the command, dataset size, model size, expected epochs/steps, test count, timeout, requested GPU/NPU, accelerator count, CPU/memory, and artifact size.
4. If a DuanFlow estimator API/SDK method is available, call it before submission with:
   - the exact inline command or function entry point,
   - relevant code/package metadata if available,
   - dataset/model size hints,
   - requested GPU/NPU/CPU/memory/disk,
   - accelerator count, timeout, parallelism, artifacts, and retry policy.
5. Use the platform estimate when available. Report that it is model-based and may improve over time as DuanFlow updates the estimator from real runs.
6. If no estimator is available, pick a conservative manual runtime estimate. If uncertain, use the requested timeout or a high estimate based on similar jobs.
7. Estimate billable accelerator time as `estimated wall time × accelerator count`. For CPU-only jobs, estimate wall time and say the exact CPU billing rate is unknown unless the account or docs provide it.
8. Estimate cost using known DuanFlow rates if available from `whoami`, `/v1/sdk/install`, project docs, pricing page, estimator output, or the job output. If no exact rate is available, use a conservative placeholder and say it is an estimate:
   - Ascend 910B: `6 CNY / card-hour`
   - A100: `8 CNY / card-hour`
   - H100: `15 CNY / card-hour`
   - Unknown GPU/NPU: use `15 CNY / card-hour`
9. Add a safety buffer of 20-50% to both time and cost unless the estimator provides a confidence interval or the user provided a strict cap.
10. Compare the estimated cost with available balance or organization credit from `duanflow whoami`.
11. If estimated balance is insufficient, do not submit the job. Tell the user the estimated shortfall and ask them to recharge or lower the job size/runtime.
12. Ask for explicit confirmation before running the job. A user choosing the cloud estimate is not enough; they must explicitly confirm submission after the final estimate.
13. After the job completes, keep the job id, submitted command/resource shape, model estimate, actual runtime, final cost, exit status, and artifact size available for DuanFlow telemetry. If the SDK has a feedback/report API, call it so future estimator training improves. Do not upload raw secrets, private data, or model weights as estimator feedback.

Use this confirmation shape:

```text
DuanFlow execution estimate:
- Account: <email or organization>
- Acceleration reason: <GPU/NPU/cloud reason>
- Command: <command>
- Local CPU estimate: <runtime range and hardware basis>
- Cloud wall-time estimate: <runtime range including startup/queue overhead>
- Accelerator: <GPU/NPU type> x <count>
- Estimated runtime: <wall time> (conservative)
- Estimate source: <DuanFlow model | manual fallback>
- Estimate confidence: <range or unknown>
- Estimated billable accelerator time: <card-hours>
- Estimated cost: <CNY> (includes buffer)
- Available balance/credit: <CNY>
- Timeout/cap: <timeout>
- Recharge reminder: cloud compute is paid; recharge first if this balance is not enough

Please confirm whether to submit this GPU job.
```

For all training/eval/benchmark tasks, present a decision shape before execution:

```text
Execution options:
- Local CPU: <total wall-time>, startup/queue/image/deps: <time>, compute: <time>, cost: <cost>, basis: <hardware/data>
- DuanFlow <accelerator>: <total wall-time>, startup/queue/image/deps: <time>, compute: <time>, estimated cost: <CNY>, billing basis: <basis>
- Script only: prepare code/artifacts without running training, estimated time: <time>, cost: <cost>

Recommendation: <local/cloud and why>
Please choose one option before I run it. I will not start local CPU training, cloud login, or paid cloud execution until you choose.
```

If balance is likely insufficient:

```text
Estimated cost is about <CNY>, but available balance/credit is <CNY>.
Please recharge at https://duanflow.zeabur.app/dashboard or ask an organization admin to add credit before I submit this job.
```

If the user asks "how long will it take" or "how much will it cost", answer with a range and call it an estimate unless you have exact current pricing and a known job profile.

Only proceed after the user confirms. If the user changes GPU type, GPU count, timeout, dataset size, epoch/step count, parallelism, or command, recalculate and ask again.

## Choose The Entry Point

Default to inline Python submission for existing repo tasks. This lets an agent run an ordinary shell command on DuanFlow cloud GPU without changing application code.

Before running any inline command, do the billing preflight above. Do not paste and execute an inline cloud command until the user has seen the estimate and confirmed.

```bash
python - <<'PY'
import subprocess
import duanflow as df

app = df.App("repo-command")

@app.function(gpu="L40S", timeout=3600, artifacts=["reports/"])
def run_command():
    subprocess.run(
        "pytest evals/ --json-report --json-report-file reports/eval.json",
        shell=True,
        check=True,
    )
    return {"ok": True}

print(run_command.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
PY
```

Choose inline Python command submission when:

- Running an existing command, script, test, benchmark, or eval.
- The task is one-off.
- You do not need to modify application code to define a stable cloud API.
- The user asked you to validate, reproduce, or inspect a result.

Choose a checked-in Python decorator when the user wants a reusable cloud function:

```python
import subprocess
import duanflow as df

app = df.App("repo-eval")

@app.function(gpu="H100", timeout=3600, artifacts=["reports/"])
def run_eval():
    subprocess.run(
        "pytest evals/ --json-report --json-report-file reports/eval.json",
        shell=True,
        check=True,
    )
    return {"report": "reports/eval.json"}

if __name__ == "__main__":
    print(run_eval.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
```

Choose decorators when:

- A function should be called repeatedly from code.
- The user wants an endpoint, job, queue worker, or stable function boundary.
- GPU, timeout, secrets, artifacts, or scaling policy should live next to the code.

## CLI Recipes

### Inline Command Recipes

Use these recipes when the agent needs to use DuanFlow cloud compute from a single inline command.

Run tests on GPU:

```bash
python - <<'PY'
import subprocess
import duanflow as df

app = df.App("gpu-tests")

@app.function(gpu="L40S", timeout=3600, artifacts=["reports/"])
def run_tests():
    subprocess.run(
        "pytest tests/ evals/ --json-report --json-report-file reports/tests.json",
        shell=True,
        check=True,
    )
    return {"report": "reports/tests.json"}

print(run_tests.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
PY
```

Run a benchmark:

```bash
python - <<'PY'
import subprocess
import duanflow as df

app = df.App("gpu-benchmark")

@app.function(gpu="A100-80G", timeout=7200, artifacts=["reports/"])
def run_benchmark():
    subprocess.run(
        "python benchmarks/batch_latency.py --out reports/latency.json",
        shell=True,
        check=True,
    )
    return {"report": "reports/latency.json"}

print(run_benchmark.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
PY
```

Run a training job:

```bash
python - <<'PY'
import subprocess
import duanflow as df

app = df.App("gpu-training")

@app.function(gpu="H100", timeout=21600, artifacts=["checkpoints/run-01", "reports/"])
def train():
    subprocess.run(
        "python train.py --config configs/lora.yaml --out checkpoints/run-01",
        shell=True,
        check=True,
    )
    return {"checkpoint": "checkpoints/run-01"}

print(train.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
PY
```

### Reusable Python GPU Function

Use this when the agent should write code that calls GPU directly, not just wrap a shell command:

```python
import duanflow as df

image = df.Image(
    base="pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime",
    python_packages=("torch", "numpy"),
)
app = df.App("torch-gpu-demo", image=image)

@app.function(gpu="H100", gpu_count=1, timeout=1800, artifacts=["reports/"])
def gpu_probe():
    import json
    import os
    import torch

    os.makedirs("reports", exist_ok=True)
    result = {
        "cuda_available": torch.cuda.is_available(),
        "device_count": torch.cuda.device_count(),
        "device_name": torch.cuda.get_device_name(0) if torch.cuda.is_available() else "",
    }
    with open("reports/gpu.json", "w", encoding="utf-8") as f:
        json.dump(result, f, ensure_ascii=False, indent=2)
    return result

if __name__ == "__main__":
    print(gpu_probe.remote(_duanflow_wait=True, _duanflow_stream_logs=True))
```

When submitting jobs, the returned object includes a `job_id`. Use the job id in the final report. If the SDK returns artifact refs or paths, include them; otherwise report the artifact directories configured in `artifacts=[...]`.

## Failure Recovery

If a DuanFlow job fails:

1. Fetch logs with the SDK:

```bash
python - <<'PY'
import json
import duanflow as df

job_id = "<job-id>"
print(json.dumps(df.Client().logs(job_id), ensure_ascii=False, indent=2))
PY
```

2. Classify the failure as dependency, code, secret, timeout, resource, data, or network.
3. Fix only the minimal cause needed to make progress.
4. Re-run the same command when possible.
5. If the failure is resource-related, try a smaller batch size before requesting a larger GPU.
6. Ask the user before increasing budget, accessing new secrets, changing network permissions, or using a more expensive GPU.

## Reporting Back

Always include:

- Job id
- Command or function run
- GPU/runtime used
- Status
- Log summary
- Artifact paths
- Any code changes made
- Next action if the job failed

Use this shape when possible:

```json
{
  "job_id": "job_8f31",
  "command": "pytest evals/ --json-report",
  "gpu": "L40S",
  "status": "success",
  "artifacts": ["reports/eval.json", "logs/events.jsonl"],
  "changes": ["reduced eval batch size from 16 to 8"]
}
```
