Prerequisites
- Python 3.12 or later.
- python and pip available in your shell.
- A virtual environment tool supported by your organization.
The released SDK supports Linux x86-64 and Linux aarch64 deployment targets. Local authoring on another operating system does not replace validation on the declared target environment.
python --version
1. Create the project
mkdir -p echo-capability/src/example_echomkdir -p echo-capability/schemasmkdir -p echo-capability/testscd echo-capability
The completed project has this structure:
echo-capability/├── capability.yaml├── pyproject.toml├── schemas/│ ├── input.json│ └── output.json├── src/│ └── example_echo/│ ├── __init__.py│ └── provider.py└── tests/└── test_provider.py
2. Create and activate a virtual environment
python -m venv .venvsource .venv/bin/activate
3. Define the Python package
Create pyproject.toml:
[build-system]requires = ["setuptools>=75.0", "wheel"]build-backend = "setuptools.build_meta"[project]name = "example-echo-capability"version = "1.0.0"requires-python = ">=3.12"dependencies = ["vega-capability-sdk>=0.1.0,<0.2.0",][project.optional-dependencies]test = ["pytest>=8.0","pytest-asyncio>=0.25",][tool.setuptools.packages.find]where = ["src"][tool.pytest.ini_options]asyncio_mode = "auto"
The bounded SDK range is intentional while the SDK is 0.x: a future minor version may contain breaking API changes.
# src/example_echo/__init__.py
Install the Capability and its test dependencies:
python -m pip install --upgrade pippython -m pip install -e ".[test]"
Verify the SDK and CLI:
python -c "import vega_capability_sdk; print(vega_capability_sdk.__version__)"vega-capability --help
4. Declare the Capability
Create capability.yaml:
apiVersion: vcp.shyda.ai/v1alpha1kind: Capabilitymetadata:id: example.echoname: Example Echoversion: 1.0.0vega:sdkVersion: ">=0.1.0,<0.2.0"provider:id: example.echo.pythonruntime: pythonentrypoint: example_echo.provider:EchoProvideractions:- id: example.echo.runversion: 1.0.0inputSchema: schemas/input.jsonoutputSchema: schemas/output.jsonexecution:cancellation: trueidempotency: idempotentcontract:description: Return a submitted string without changing the world.can:- Return a string supplied by the caller.cannot:- Control hardware or produce physical effects.requires:- Input that satisfies the Action input schema.guarantees:- Returns the submitted string after a successful execution.limitations:- This Capability is an SDK tutorial only.
Every Action requires a contract. It is bounded, human-authored evidence for planning and review; it is not executable authorization or safety policy. The provider.entrypointvalue matches the installed Python module and class: example_echo.provider:EchoProvider.
5. Define the schemas
Create schemas/input.json:
{"$schema": "https://json-schema.org/draft/2020-12/schema","type": "object","additionalProperties": false,"required": ["text"],"properties": {"text": { "type": "string", "minLength": 1, "maxLength": 1000 }}}
Create schemas/output.json:
{"$schema": "https://json-schema.org/draft/2020-12/schema","type": "object","additionalProperties": false,"required": ["text"],"properties": {"text": { "type": "string" }}}
The SDK validates that these are valid JSON Schema Draft 2020-12 documents. Runtime validates execution payloads at the appropriate public boundary. Provider code should still validate semantic conditions that schemas cannot express reliably.
6. Implement the Provider
Create src/example_echo/provider.py:
from vega_capability_sdk import (BaseCapabilityProvider,CapabilityExecutionRequest,CapabilityExecutionResult,InvalidInputError,PhysicalTerminationStatus,)class EchoProvider(BaseCapabilityProvider):async def on_execute(self,request: CapabilityExecutionRequest,context,) -> CapabilityExecutionResult:context.validate_request(request)text = request.inputs.get("text")if not isinstance(text, str) or not text.strip():raise InvalidInputError("text must be a non-empty string")context.cancellation.raise_if_cancelled()context.logger.info("echo execution started", action_id=request.action_id)return CapabilityExecutionResult(output={"text": text},physical_termination=PhysicalTerminationStatus.NOT_APPLICABLE,)
The Provider overrides on_execute, not execute, so the base class can enforce lifecycle state, validate execution identity, and convert unexpected execution exceptions to ProviderInternalError.
7. Validate the package
vega-capability validate . --json
A successful result resembles:
{"valid": true,"capability_id": "example.echo","version": "1.0.0","actions": ["example.echo.run"],"digest": "..."}
Package validation checks the manifest, SDK range, Action contract, schema documents, resource references, and referenced path containment. It does not import or execute the Provider.
8. Test the Provider
Create tests/test_provider.py:
import pytestfrom example_echo.provider import EchoProviderfrom vega_capability_sdk import CapabilityExecutionRequestfrom vega_capability_sdk.manifests import validate_capability_packagefrom vega_capability_sdk.testing import ProviderContractHarness@pytest.mark.asyncioasync def test_provider_contract() -> None:definition = validate_capability_package(".")action = definition.action_by_id("example.echo.run")assert action is not Nonerequest = CapabilityExecutionRequest(execution_id="test-execution",capability_id="example.echo",provider_id="example.echo.python",action_id="example.echo.run",action_version="1.0.0",inputs={"text": "hello"},)report = await ProviderContractHarness().run(EchoProvider(),request,action=action,)report.raise_for_failures()
pytest -q
The harness exercises initialization, health, execution, output-schema validation, and shutdown using SDK test contexts. It does not start Runtime and does not prove hardware safety.
What you built
- A Capability package that installs as a Python package.
- An importable module:Class Provider entrypoint.
- A VCP-compatible manifest and Action contract.
- Validation that runs without importing Provider code.
- A passing SDK lifecycle conformance harness run.
