Skip to content

Latest commit

 

History

History
317 lines (259 loc) · 14.3 KB

README_en.md

File metadata and controls

317 lines (259 loc) · 14.3 KB

PhyAgentOS Integration Development Guide

中文 · Documentation index

Version: 1.0.0

1. Choose the integration point

Capability Integration point
Robot read or calculation Gateway Query ToolSpec + ToolEndpoint operation
Robot effect Gateway Action ToolSpec + ToolEndpoint operation
Stateful capability lifecycle Gateway Session ToolSpec + ToolEndpoint operation
Dora nodes and deployment assets Manifest-v2 Skill Bundle and locked Node artifacts
Workflow instructions SKILL.md discovered by SkillsLoader
User-task success Generic TaskVerificationContract and AgentTask finalize
New model provider Existing provider registry/configuration
Non-robot Agent capability Existing Agent ToolRegistry or dynamic MCP

Do not connect Agent code directly to robot SDKs, Dora nodes, simulators, or legacy Gateway Session/Policy routes outside the governed Tool API.

2. Define a ToolSpec

Every ToolSpec has a stable tool_id, implementation and endpoint binding, operation, semantics: query|action|session, description, strict input/output JSON schemas, readiness requirements, and a robot frame profile when spatial inputs are involved.

tool_id: motion.resolve_relative_pose
implementation_id: motion.integration
endpoint_id: motion.relative_pose
operation: resolve
semantics: query
description: Resolve a relative end-effector delta into an absolute target pose.
input_schema:
  type: object
  additionalProperties: false
  required: [translation_frame, translation_m]
  properties:
    translation_frame: {enum: [tcp, base]}
    translation_m:
      type: object
      additionalProperties: false
      required: [x, y, z]
      properties:
        x: {type: number}
        y: {type: number}
        z: {type: number}
output_schema:
  type: object
robot_frame_profile:
  base_frame: arm_base
  tool_frame: tcp

Use Query for synchronous reads or deterministic resolution without a robot effect. Use Action for bounded physical effects and Session for explicitly owned, stateful lifecycles. Define Endpoint operation max_concurrency at the execution owner; PAOS does not create a cross-Tool lease.

3. Implement Query, Action, and Session behavior

Query calls are resolved from ToolSpec and invoked at:

POST /tools/{endpoint_id}/{operation}:invoke → HTTP 200

Action admission uses:

POST /tools/{tool_id}:invoke → HTTP 202 + invocation_id + attempt_id
GET  /invocations/{invocation_id}
GET  /invocations/{invocation_id}/result
POST /invocations/{invocation_id}/cancel

Session admission uses the same POST /tools/{tool_id}:invoke contract. Reconcile it through the common invocation routes and stop it with POST /invocations/{invocation_id}/stop. Declare whether the Session is task-owned, shared, or runtime-owned; do not let one owner stop another owner's Session.

Action status/result must expose an explicit lifecycle. Result may remain pending with HTTP 202. Cancellation acceptance reports control handling only. When execution truth cannot be recovered, return an explicit unknown outcome rather than fabricating cancellation or success.

Inputs and outputs must be finite JSON and satisfy ToolSpec. Spatial Tools must state frames, units, tolerances, and orientation behavior. Avoid hidden defaults that the Agent cannot inspect through forge_tool_context.

4. Build a manifest-v2 Skill Bundle

An installed Skill Bundle contains:

<skill>/
├── skill.yaml
├── SKILL.md
├── start.sh                    # optional external-resource preparation before Dora
├── archive-manifest.json       # generated by the packaging script
├── profiles/<profile>/dataflow.yaml
├── profiles/<profile>/...
└── assets/...

Minimal manifest structure:

manifest_version: 2
name: example-skill
version: "1.0.0"
description: Example robot workflow.
skill_document: SKILL.md
gateway_url: http://127.0.0.1:19002
required_tools: [example.query, example.action]
profiles:
  sim:
    dataflow: profiles/sim/dataflow.yaml
    # optional: overrides the Skill-wide required_tools; omit to inherit
    required_tools: [example.query]
    required_binaries: [gateway, example_node]
    required_assets: [assets/scene.xml]
    required_environment: []
    environment: {}
artifacts:
  resolver: registry
  nodes:
    gateway:
      artifact_id: gateway-1.0.0-linux-x86_64
      version: "1.0.0"
      platform: linux
      arch: x86_64
      artifact_type: executable_tar_gz
      entrypoint: gateway
      sha256: <64-character-sha256>

All paths are relative and contained by the Bundle. Each Node archive has the locked SHA-256. An executable_tar_gz archive contains exactly one root-level executable with the locked filename; a directory_tar_gz archive contains exactly one root directory named after the entrypoint that holds the same-named executable and its runtime tree (tree-internal relative symlinks only). The installer records the extracted binary hash in its receipt. The Bundle archive inventory must cover every file with SHA-256. Links, path traversal, collisions, oversized expansion, and unlisted content are rejected.

When startup must download weights or prepare other external resources, the Bundle may provide a root-level start.sh. PAOS invokes it as bash <bundle>/start.sh <name> <version>, preserves the caller's working directory, and inherits terminal stdio. The script should resolve Bundle files relative to its own location, tolerate repeated execution, and return non-zero on failure. Such a Bundle requires Bash on the host PATH. PAOS_SKILL_NAME and PAOS_SKILL_VERSION are available as dataflow placeholders and in Dora process environments.

Hook environment contract: PAOS also passes PAOS_SKILL_PROFILE (the profile being started), PAOS_SKILL_ROOT (the Bundle root), and PAOS_HOOK_PYTHON (the interpreter running PAOS Core). PAOS_HOOK_PYTHON is only guaranteed to import Core's own dependencies, not any model-runtime dependency: create your own virtual environment or call an external tool when the hook must prepare CUDA PyTorch, transformers, or similar.

profiles.<profile>.required_tools is optional: when present it overrides the Skill-wide required_tools, and a profile that omits it inherits that list. The field carries two contracts at once - the Tool set the startup and status health checks require, and the Tool allowlist the AgentTask may call (forge/binding.py freezes the same list into the AgentTask). One Bundle can therefore expose a different Tool surface per profile while both checks stay in agreement for a given profile.

profiles.<profile>.required_tools needs a PAOS Core that knows the field. An older Core, including v1.0.0, rejects the whole Bundle with profiles.<profile> has unknown field(s): required_tools, so Bundles using it should state their minimum Core version.

5. Package, publish, and close the local loop

5.1 Build and validate a Bundle

The repository script regenerates archive-manifest.json, builds a deterministic archive with fixed metadata, and safely extracts it through ArchiveValidator for final verification:

python scripts/package_skill.py /path/to/example-skill --output-dir dist/skills

The output name comes from name and version in skill.yaml; the script prints the archive SHA-256 and byte size. It refuses to replace an existing output unless --force is supplied; use that option only before publication. The script rejects links and excludes version-control, cache, and node_modules directories. Do not put credentials, presigned URLs, machine caches, logs, or runtime state in the source directory.

Before upload, run the same public local loop that users depend on:

paos skill install dist/skills/example-skill-1.0.0.tar.gz --local
paos forge-node verify example-skill gateway
paos skill inspect example-skill
paos skill start example-skill --profile sim
paos skill status example-skill
paos skill stop example-skill

A local Bundle uses the same archive, manifest, and Node-lock validation as a Registry Bundle. Missing Nodes still resolve through the configured Registry or static index. Installers stage, validate, atomically replace, and roll back on failure. Never require callers to disable digest verification.

5.2 Immutable publication order

  1. Publish and register every Node artifact first. An executable_tar_gz archive contains only one root-level executable named by entrypoint; a directory_tar_gz archive contains only one root directory named by entrypoint (holding the same-named executable and its runtime tree). Put the final archive SHA-256 in the Skill lock.
  2. Freeze the skill.yaml name/version, profiles, and Node locks, package the Bundle, and retain the printed Bundle SHA-256 and size_bytes.
  3. Upload the Bundle to a non-overwritable, long-lived HTTPS object key. Read it back from the final URL and verify size and SHA-256. Corrections require a new version instead of overwriting bytes.
  4. Register the current Skill name, URL, SHA-256, and size in the Resource Registry, and ensure every Node artifact_id resolves through its Node endpoint. An equivalent schema-v3 static index is also supported.
  5. From a clean PAOS HOME, repeat Registry install, start, status, and stop. Confirm that no source checkout path or development-machine cache is required.

The public Registry returns the current Skill entry by name and has no historical-version subpath. The version in paos skill install <name> --version <version> is a client constraint: after the Bundle download, PAOS verifies its manifest version and rejects a mismatch before Node download or installation commit. Preserve old versions through immutable URLs, static indexes, or local archives; do not treat --version as a Registry history query.

6. Design the Dora profile

Develop and validate the currently distributed Forge Skill profiles with Dora CLI v0.4.1 and dora-message v0.7.0. Keep Node builds on that protocol generation until the Skill locks and host baseline are upgraded together.

The dataflow should give each node explicit inputs/outputs and use the Gateway Tool request/response ports declared in its profile. Required executables are resolved from the immutable Runtime environment. Assets remain in the Skill Bundle and are referenced with relocatable paths.

RuntimeManager creates a deterministic flow name, verifies Dora and required files, starts the flow, then waits for Gateway /tools and every required Tool context. A Gateway already listening at the manifest URL is not silently adopted.

When Tool API is the physical execution plane, disable the Gateway Agent API in the profile:

agent:
  enabled: false
tools:
  enabled: true

7. Write workflow guidance

SKILL.md should tell the Agent when to activate the Skill, which contexts to inspect, the Query → Action/Session ordering, task binding, ownership, terminal reconciliation, verification checkpoints, and safe recovery rules. It must not embed secrets, Registry URLs, task-specific coordinates, or instructions to bypass Gateway/verification.

For a verified workflow, activate the primary Skill in the current turn, create one AgentTask from that activation, bind every contributing Query/Action/Session to the same task, finalize after all task-owned executions terminate, and append a PlanRevision only when recovery verdict allows it.

8. Evidence and verification

Robot capability integration should expose Tool execution facts, not action-specific verifier code. PAOS captures configured image/state sources and applies the generic verification contract at AgentTask finalize. Tool output schemas should contain useful terminal result semantics, final state/error data, and tolerances where relevant.

If authoritative evidence is introduced later, version the evidence contract explicitly. Do not upgrade best-effort WebSocket association by convention.

9. Fake Gateway and conformance tests

Before real hardware or simulation, use a mock HTTP transport to test:

  • Tool list/spec/context and Query binding resolution;
  • activation candidate revalidation and ToolSpec/runtime drift rejection;
  • Action HTTP 202 admission with invocation and attempt identities;
  • Session admission, ownership, status/result, and stop;
  • pending status/result and known terminal results;
  • cancellation requested/accepted without false stop;
  • timeout and unknown without blind retry;
  • endpoint concurrency rejection behavior;
  • diagnostic Query and bound calls through identical routes;
  • AgentTask one-active constraint, revisions, evidence, and aggregate verification;
  • archive traversal/link/collision/digest attacks and transactional rollback;
  • startup with and without start.sh, missing Bash, and non-zero hook exit;
  • Skill identity injection into dataflow/Dora environments and rematerialization after profile content or dataflow-path changes;
  • cross-process start/stop/install/remove conflicts for one Skill;
  • Runtime start/status/log/stop and availability propagation.

Then run a complete simulated workflow. Real robot or MuJoCo acceptance must identify the exact Bundle, node digests, profile, and environment used.

10. Integration acceptance checklist

  • Tool semantics and schemas are explicit and strict.
  • Frame, unit, tolerance, and readiness conventions are inspectable.
  • Gateway operation owns max_concurrency.
  • Query, Action, and Session use the documented HTTP contracts.
  • Skill/Runtime/ToolSpec binding is frozen and revalidated for every governed execution.
  • Invocation and attempt IDs remain separate from PAOS task IDs.
  • Cancel, stop, timeout, and unknown do not imply physical stop or trigger a blind POST retry.
  • Bundle and Node artifacts have immutable size/digest metadata.
  • The Bundle passes repository packaging and the local install loop, and Registry Skill and Node endpoints all resolve.
  • Optional startup-hook arguments, failure state, repeated execution, and external-resource digests are verified.
  • Runtime profile starts from a clean environment and reaches all Tool contexts.
  • Gateway Agent API is disabled for the Tool-only profile.
  • General Agent tools, verification, experience, and evolution require no capability-specific fork.

Next reading