Vega SDK — Python

Best Practices

Design and operational recommendations for building maintainable, safe, and compatible Python Capabilities with the Vega Capability SDK. Apply these together with your organization's robotics safety, security, testing, and release requirements — the SDK does not replace them.

Concepts

TermMeaning
Contract-first designManifest, schemas, and behavior evolve together.
Adapter boundaryVendor/hardware logic is separate from Provider code.
Operational evidenceResults, diagnostics, health, and recovery reflect facts rather than assumptions.

Recommended layout

text
capability/
├── capability.yaml
├── pyproject.toml
├── schemas/
│ ├── input.json
│ ├── output.json
│ └── progress.json
├── config/
│ └── default.yaml
├── src/
│ └── package_name/
│ ├── __init__.py
│ ├── provider.py
│ └── adapter.py
└── tests/
├── unit/
├── contract/
└── integration/

The manifest entrypoint must match an importable installed module and class, for example package_name.provider:Provider.

Separate Provider and adapter responsibilities

The Provider should translate between the public VCP contract and a small Capability-owned backend interface. The adapter owns vendor SDK calls, ROS integration, device protocols, and service-specific data. This boundary makes contract tests independent of hardware and prevents vendor objects from leaking into public output.

Avoid:

  • Importing Runtime internals.
  • Connecting to hardware during module import.
  • Returning vendor response objects.
  • Placing scheduling or mission logic inside the Capability.
  • Coupling Action schemas directly to unstable vendor payloads.

Design the public contract first

For each Action:

  • Define the observable real-world behavior.
  • Write input, output, and optional Progress schemas.
  • State can, cannot, requires, guarantees, and limitations using facts the backend can support.
  • Declare cancellation, pause, resume, idempotency, resources, and recovery conservatively.
  • Implement Provider behavior and tests against that contract.

Treat schema and contract changes as public API changes. Reject unknown input properties when forward-compatible extension is not intended.

Design, errors, and logging

Keep Actions narrow. Declare resources, idempotency, cancellation, progress, and restart recovery conservatively. Raise specific standard errors and include only JSON-compatible, non-secret details. Use StructuredLogger with execution context and never log a raw SecretValue.

TermMeaning
Semantically invalid inputInvalidInputError
Required device state is absentPreconditionFailedError
External dependency is unavailableDependencyUnavailableError
Assigned resource cannot be usedResourceUnavailableError
Device operation failedHardwareError
Transport or external API communication failedCommunicationError
Provider-observed deadline expiredTimeoutCapabilityError
Safety or policy rejected the operationSafetyRejectionError
Action or backend mode is unsupportedUnsupportedOperationError
python
logger = context.logger.bind(
action_id=request.action_id,
backend="primary",
)
logger.info("execution started")

Do not log entire request payloads by default.

Testing and performance

Run manifest validation, unit tests, static analysis, and the conformance harness in CI. Use mock adapters and fake contexts first; run hardware tests separately. Avoid blocking calls, unbounded buffers, raw task creation, and large inline output. Use injected clock and Artifact services.

TermMeaning
UnitInput semantics, error mapping, adapter translation, pure functions.
Provider contractLifecycle, result type, optional output-schema validation.
Package validationManifest, schema, contract, resources, SDK range.
IntegrationReal vendor client or service in a controlled environment.
HardwarePhysical effects, stop behavior, safety, recovery, environmental limits.

Test negative behavior as deliberately as success:

  • Initialization failure and retry.
  • Cancellation before and during backend I/O.
  • Timeout and service unavailability.
  • Invalid semantic input.
  • Output and Progress schema mismatch.
  • Shutdown with work in flight.
  • Uncertain physical termination.
  • Restart-time unknown, not_found, and unavailable.

The conformance harness is necessary but not sufficient: it does not start Runtime or prove physical safety.

Bound resource consumption

  • Bound Action input with schemas.
  • Bound Progress payload size and reporting frequency.
  • Use Artifact storage for bytes and large results.
  • Apply timeouts to downstream I/O where the dependency supports them.
  • Avoid synchronous blocking calls on the event loop.
  • Cancel and await execution-local tasks.
  • Keep diagnostics and raw recovery facts small and non-secret.
  • Load-test expected concurrency against the real adapter.

Security and compatibility

Store only secret names in manifests and retrieve values from SecretAccessor. Use bounded SDK ranges while the SDK is 0.x, such as >=0.1.0,<0.2.0. Update manifest version, Python package version, Action versions, schemas, and changelog coherently.

Do not put real secrets in:

  • capability.yaml or configuration defaults.
  • Schema examples.
  • Source code or tests.
  • Logs and exception messages.
  • Progress events.
  • Result output or diagnostics.
  • Artifact metadata.
  • Recovery raw facts.

Treat downstream trace headers and Artifact URIs as potentially sensitive operational data.

Release and compatibility

Before changing an Action, determine whether existing consumers can continue to send the old input and interpret the new output. Increment the Action version when its contract changes incompatibly. Keep four version domains distinct:

  • SDK dependency range.
  • VCP apiVersion.
  • Capability package version.
  • Individual Action version.

Build releases from a clean, reproducible environment. Pin or constrain Capability-owned dependencies, publish a changelog, and test the exact wheel or package artifact intended for deployment.

Production checklist

  • Manifest validates with vega-capability validate.
  • Input, output, and declared progress schemas match Provider behavior.
  • Health, cancellation, shutdown, and recovery claims have tests.
  • Secrets and diagnostics have been reviewed for leakage.
  • Physical termination and idempotency declarations are evidence-based.
  • Compatibility is tested on the declared target environment.
  • Provider entrypoint imports from an installed wheel or editable package.
  • Dependency and license review is complete.
  • Unit, contract, integration, and required hardware tests pass.
  • Cancellation and physical termination behavior is documented.
  • Recovery claims match durable backend evidence.
  • Logs, Progress, results, errors, and Artifacts have bounded data.
  • Upgrade and rollback procedures are documented.

Common anti-patterns

  • One Provider attribute stores mutable state for all executions.
  • asyncio.create_task() starts work that shutdown cannot find.
  • A recovery probe replays a non-idempotent operation.
  • PhysicalTerminationStatus.CONFIRMED is based only on coroutine completion.
  • A local absolute path is returned instead of an Artifact reference.
  • A redacted secret wrapper is converted to raw text and then logged.
  • Compatibility declarations are broader than the tested hardware matrix.
  • Manifest validation is treated as Provider import or execution validation.