Example: Code into a Repo
Emit code files directly into a working repo (clone) using targetSlot.kind: 'repos'.
Not runnable today. This example depends on the workspace harvest, which is not running: files the agent writes into the repo working copy do not become artifacts, so
open-prhas no artifact ids to build a PR from. The spec and itstargetSlotare still valid. See the note on the section index.
Spec
1{
2 "ref": "engineering-standard",
3 "kind": "custom",
4 "outputContract": {
5 "title": "Engineering Implementation",
6 "mode": "workspace-files",
7 "targetSlot": {
8 "kind": "repos",
9 "repoSlug": "my-service"
10 },
11 "notes": "Agent writes source files, configs, and migrations under the repo working copy. Repo slug is supplied by the workflow context."
12 }
13}The custom kind doesn't constrain individual file paths — the agent is free to add, modify, or delete files in the repo working copy. Validation only checks that some files were written.
For tighter contracts (e.g. "must touch these specific files"), use custom with an explicit files[] block listing required paths.
Workflow
1apiVersion: xema.dev/workflow/v1alpha1
2kind: Workflow
3metadata:
4 name: code-emission-example
5 version: 1.0.0
6on:
7 workflow_dispatch:
8 inputs:
9 changeRequest:
10 type: string
11 required: true
12permissions:
13 artifacts: write
14 repos: write
15jobs:
16 engineer:
17 title: Engineering implementation
18 uses: xema/agent
19 with:
20 agentRef: engineering
21 stageKey: engineering
22 deliverableSpecRef: engineering-standard
23 agentSession: false
24 agentContext:
25 prompt: ${{ inputs.changeRequest }}
26 permissions:
27 repos: write
28 outputs:
29 handoff: ${{ job.outputs.structuredOutput }}An open-pr job consuming outputs.deliverables used to follow here. It is
removed rather than rewritten: that output no longer exists, so the job would
name a field the action does not declare and open a pull request over no
files.
Reading the result
This is the envelope the harvest was designed to expose. It is not produced today — shown so the spec's intent is legible, not as something to consume:
1agentResult: {
2 deliverable: {
3 specRef: 'engineering-standard',
4 kind: 'custom',
5 targetSlot: { kind: 'repos', repoSlug: 'my-service' },
6 content: {
7 kind: 'custom',
8 files: [
9 { path: '/workspace/repos/my-service/src/handler.ts',
10 artifactId: 'art-1', versionId: 'ver-1', version: 1,
11 contentKind: 'text', sizeBytes: 1840 },
12 { path: '/workspace/repos/my-service/test/handler.test.ts',
13 artifactId: 'art-2', versionId: 'ver-2', version: 1,
14 contentKind: 'text', sizeBytes: 920 },
15 { path: '/workspace/repos/my-service/migrations/2026-05-01-init.sql',
16 artifactId: 'art-3', versionId: 'ver-3', version: 1,
17 contentKind: 'text', sizeBytes: 412 },
18 ],
19 },
20 },
21}A downstream scm-open-pr action would consume those artifact ids to build a PR with all written files.
Validating the result
xema/validate-deliverables is live and checks artifact counts, so it is what
would make "the agent wrote nothing usable" visible. With the harvest not
running there are no file artifacts to count, so a custom spec validated this
way returns fail with INSUFFICIENT_ARTIFACTS on every run — not because the
agent misbehaved, but because nothing collects what it wrote. See
04 Validation.
Tighter contracts
Add a files[] block to require specific paths exist:
1"files": [
2 {
3 "canonicalPath": "src/handler.ts",
4 "required": true,
5 "purpose": "Main request handler",
6 "contentKind": "text"
7 }
8]files[] is the list of paths the harvest was to consider, in order, when
looking for the deliverable. It is part of the spec contract and is still
stored and served; nothing walks it today.
Previous: ← JSON schema Next: Response-only →