Skip to main content
Submission Groups are the control-plane primitive for large workload batches.
  • Type is fixed per group:
    • simulation
    • training
  • Each group has one group_id
  • Each line item is tracked independently (partial accept is supported)

Why Use Groups

  • Submit many items in one flow (up to configured max per group)
  • Track aggregate progress with one ID
  • Inspect per-item errors without losing successful items
  • Cancel remaining queued/running work at group level

API Endpoints

  • POST /v1/submission-groups
  • POST /v1/submission-groups/{group_id}/ingest
  • GET /v1/submission-groups/{group_id}
  • GET /v1/submission-groups
  • GET /v1/submission-groups/{group_id}/items
  • GET /v1/submission-groups/{group_id}/events
  • POST /v1/submission-groups/{group_id}/cancel

SDK Shortcuts

  • client.submit_many_jobs(...)
  • client.submit_many_training_runs(...)
  • client.watch_submission_group(group_id, ...)
  • client.list_submission_group_items(group_id, ...)
  • client.cancel_submission_group(group_id)

Example: Batch Simulation Submit

import hardsim as hs

client = hs.HardsimClient.from_env()

group = client.submit_many_jobs(
    name="franka-grid-10",
    jobs=[
        {
            "job_type": "rollout",
            "robot": {"urdf_asset_id": "asset_robot_fr3"},
            "scene": {"usd_asset_id": "asset_scene_table"},
            "physics": {"dt": 0.005, "substeps": 2},
            "execution": {"num_envs": 8, "steps": 512, "seed": i + 1},
            "outputs": {"video": True, "log_format": "zarr"},
            "control": {"task_mode": "fr3_pick_lift_block_v1", "fix_base": True},
        }
        for i in range(10)
    ],
)

group_id = group["group_id"]
print("group:", group_id)

Monitor From Terminal

result = client.watch_submission_group(
    group_id,
    poll_interval_s=2.0,
    timeout_s=3600,
)
print(result["status"])

Item-Level Debugging

items = client.list_submission_group_items(group_id, limit=500)["items"]
failed = [x for x in items if x["status"] in {"invalid", "failed", "submit_failed"}]
for item in failed[:20]:
    print(item["line_no"], item.get("error_code"), item.get("error_detail"))

Filter Existing Workloads By Group

  • GET /v0/jobs?submission_group_id=<group_id>
  • GET /v1/training-runs?submission_group_id=<group_id>
These filters are also available in the customer dashboard UI.