Lab · Give a Pico Hands
See the Open Engineering Language Server (OELS) onboarding guide for the local install and editor setup.
While you work through this content, keep the Open Engineering Language Server (OELS) active in VS Code (or any LSP-capable editor). See the OELS onboarding guide linked at the top of this page (also linked from the academy Resources page) for the one-time install and configuration steps.
What OELS validates. OELS only recognizes OE-shaped YAML/JSON: files with a mapping root that declare an apiVersion beginning with open-engineering.io/, a non-empty kind, and a DNS-1123 metadata.name. Ordinary academy metadata.yaml, Quarto/QMD pages and front matter, Kubernetes/Crossplane/runtime manifests, JSON payload samples, and shell scripts are intentionally non-OE — OELS ignores them silently and you should not add synthetic apiVersion/kind headers to force recognition.
Where you see diagnostics. OELS surfaces UnknownProperty, MissingRequiredProperty, IncorrectType, InvalidEnumValue, MalformedIdentifier, UnknownDefinition, and reference-shape hints in the editor Problems panel as you type. These are independent of quarto render: OELS diagnostics do not block rendering, and Quarto errors do not appear in the Problems panel.
The executable check still comes from this exercise. OELS speeds up editing, but the exercise’s own parser, verifier, or verify.sh (for example the pico parse … command shown below) remains the authoritative success check. Run it as usual.
In this lab you will author one artefact per stage of a Hand invocation — Composer equipment, Pico decision, Policy authorization, Hand selection, Provider execution, Evidence, and Action event — and validate the local YAML with the pico CLI.
The scenario follows the memo progression: a Pico observes a condition, evaluates a rule, decides on an action, its Hand carries the action out, an evidence record is kept, and an action event is published.
Every step in this lab operates on local YAML only. No step contacts Composio, GitHub, Kubernetes, or any other external service. The provider mapping in Step 6 is a labeled, optional, non-runnable annex — nothing in it executes.
Setup
mkdir -p scratch/handsStep 1 — Composer equipment (Pico definition with Hands)
Create scratch/hands/pico.yaml. This is what the Composer puts on the Pico. It says only what capabilities are available, not what is permitted.
# scratch/hands/pico.yaml
apiVersion: open-engineering.io/v1alpha1
kind: Pico
metadata:
name: issue-reporter
spec:
hands:
- name: external
provider: local # provider-neutral placeholder
capabilities:
- github.issue.read
- github.issue.create
- name: cluster
provider: local # provider-neutral placeholder
capabilities:
- kubernetes.resource.readStep 2 — Pico decision (governed action request)
Create scratch/hands/action.yaml — the “identity before action” boundary. This is the Pico’s decision to invoke a capability, not yet the authorization or the execution.
# scratch/hands/action.yaml
actor:
pico: issue-reporter
principal:
type: user
id: user.example
action:
capability: github.issue.create # provider-neutral
authorization:
capability: github.issue.createStep 4 — Hand selection
Create scratch/hands/selection.yaml. This records which specific Hand on the Pico is bound to carry out the authorized capability.
# scratch/hands/selection.yaml
selection:
capability: github.issue.create
hand: external
rationale: "only 'external' declares github.issue.create in step 1"Step 5 — Provider execution (simulated)
Create scratch/hands/execution.yaml. This is a simulated provider result. Nothing is actually contacted — the artefact just describes what a provider would return so later stages can consume it.
# scratch/hands/execution.yaml
execution:
hand: external
capability: github.issue.create
provider: local # simulated; no external call
status: succeeded
provider-reference: "sim://issue/42"Step 6 — Evidence
Create scratch/hands/evidence.yaml. Evidence is a signed, retainable record of what happened, distinct from the action itself.
# scratch/hands/evidence.yaml
evidence:
actor: issue-reporter
principal: user.example
capability: github.issue.create
authorized-by: rules/rules.yaml#0
hand: external
execution-reference: "sim://issue/42"
outcome: succeeded
observed-at: 2026-01-01T00:00:00ZStep 7 — Action event
Create scratch/hands/event.yaml. This is the Pico’s Voice reporting a state transition after the Hand acted. Other Picos, services, or humans can subscribe to it.
# scratch/hands/event.yaml
event:
type: pico.hand.executed
source: issue-reporter
capability: github.issue.create
outcome: succeeded
evidence-reference: evidence/evidence.yamlStep 8 — Validate all seven
Every file is local YAML. No network is used. These are Hands governance artefacts rather than Hello Pico Rules, so the check uses python3 to confirm each file is well-formed YAML — pico parse only accepts the flat Rule shape (id/kind/value) taught in Part 1.
python3 - <<'PY'
import sys, yaml, pathlib
root = pathlib.Path("scratch/hands")
failed = False
for name in ("pico", "action", "rules", "selection", "execution", "evidence", "event"):
path = root / f"{name}.yaml"
try:
doc = yaml.safe_load(path.read_text())
except yaml.YAMLError as exc:
print(f"FAIL: {path} — {exc}", file=sys.stderr); failed = True; continue
if not isinstance(doc, dict) or not doc:
print(f"FAIL: {path} — expected a non-empty YAML mapping", file=sys.stderr)
failed = True; continue
print(f"OK: {name}.yaml parses")
sys.exit(1 if failed else 0)
PYStep 9 — Optional annex · Composio provider mapping (non-runnable)
This annex illustrates what a provider mapping for Composio could look like. It is not executed and is not a prerequisite for completing the lab. No credentials, tokens, or Composio account are needed.
# scratch/hands/composio-mapping.yaml (illustrative only — do not run)
provider: composio
mappings:
github.issue.create: GITHUB_CREATE_ISSUE
email.send: GMAIL_SEND_EMAILThe Pico rules in Step 3 still name only github.issue.create. Swapping the provider means swapping this mapping — nothing else changes.
For a deeper walk-through of this mapping — including a mock contract check that runs on local YAML and asserts rules stay provider-neutral, no credential-shaped strings appear, and the Composio-specific vocabulary is confined to the adapter surface — see the optional, non-runnable follow-up page: Composio as a Hands provider.
Step 10 — Reflect
Answer, using your files:
- Which file expresses what the Pico can be equipped to do (equipment)?
- Which file expresses what the Pico is permitted to do in a given context (policy authorization)?
- Why is the action request tied to an actor and capability rather than only a provider tool?
- Why do evidence and action event exist as separate artefacts?
- What extra constraint would you add to require human approval for a production
github.issue.create?
What you will produce
Seven local YAML artefacts — one per stage of the Hand invocation — plus an optional, non-runnable Composio mapping annex. Together they show Hands as governed execution with clear separation between equipment, decision, authorization, selection, execution, evidence, and action events.
Next
Continue with the Summary.