Agent Handoff Validator
agent.handoff_validate
Overview
You send a packet with status IN_PROGRESS, BLOCKED or COMPLETE plus optional objective, completed, remaining, artifacts, constraints, blockers and nextAction. requiredFields selects from OBJECTIVE, STATUS, COMPLETED, REMAINING, ARTIFACTS, CONSTRAINTS, BLOCKERS and NEXT_ACTION. COMPLETE cannot keep remaining work; BLOCKED needs at least one blocker; artifact ids must be unique. This does not send the handoff, fetch artifacts or check whether the work is true.
A second agent that consumes a contradictory COMPLETE packet wastes a turn.
Reliability
Deterministic invariant checks; no clock or network. HANDOFF_INVALID — trigger: an unknown requiredFields value, an empty identifier, or an over-long string; retryable: no; next: send the published enum and bounded ids.
Context footprint
Verdict, counts and diagnostics only. A successful call costs 1 execution credit.
When to use it
When one agent is about to hand work to another and the packet must be internally consistent.
When you need to send the packet, fetch artifacts, or judge whether the work is true.
Scope
Non-goals
- Does not send a handoff
- Does not fetch artifacts
- Does not verify that work is true
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response does not contain submitted content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | Yes | Packet status from the published three-value lattice. |
| objective | string | No | Optional objective text. Omit it when the packet has none. |
| completed | array | No | Optional completed item ids, 0 through 500 unique strings of 1 through 256 characters. Omit it for none. |
| remaining | array | No | Optional remaining item ids, 0 through 500 unique strings of 1 through 256 characters. Omit it for none. |
| artifacts | array | No | Optional artifact ids, 0 through 500 unique strings of 1 through 256 characters. Omit it for none. |
| constraints | array | No | Optional constraint ids, 0 through 500 unique strings of 1 through 256 characters. Omit it for none. |
| blockers | array | No | Optional blocker ids, 0 through 500 unique strings of 1 through 256 characters. Omit it for none. |
| nextAction | string | No | Optional next action text. Omit it when the packet has none. |
| requiredFields | array | No | Optional extra required section names from the published enum, 0 through 8 strings. Omit it for the default published set. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| valid | boolean | Yes | True when no ERROR diagnostic was raised. |
| status | string | Yes | The judged packet status. |
| completeness | object | Yes | Closed completeness counts for completed, remaining, artifacts, blockers and nextAction. |
| diagnostics | array | Yes | Normalized findings as a bounded array of 0 through 500 closed {code, severity, message, path, source, details} objects. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"agent.handoff_validate","input":{"status":"COMPLETE"}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("agent.handoff_validate", {"status":"COMPLETE","constraints":["no-live-certify"],"objective":"Ship the bounded loop detector","artifacts":["pr-loop"],"remaining":[],"completed":["spec","tests"]});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| HANDOFF_INVALID | 400 | No | The request payload failed this skill's input validation. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not send a handoff
- Does not fetch artifacts
- Does not verify that work is true
- Creating or routing the handoff
- Checking artifact access
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "agent.handoff_validate",
"input": {
"status": "COMPLETE",
"constraints": [
"no-live-certify"
],
"objective": "Ship the bounded loop detector",
"artifacts": [
"pr-loop"
],
"remaining": [],
"completed": [
"spec",
"tests"
]
}
}Examples
A COMPLETE packet with empty remaining is valid
{
"status": "COMPLETE",
"constraints": [
"no-live-certify"
],
"objective": "Ship the bounded loop detector",
"artifacts": [
"pr-loop"
],
"remaining": [],
"completed": [
"spec",
"tests"
]
}{
"valid": true,
"diagnostics": [],
"completeness": {
"completedCount": 2,
"remainingCount": 0,
"artifactCount": 1,
"blockerCount": 0,
"hasNextAction": false
},
"status": "COMPLETE"
}COMPLETE cannot carry remaining work
{
"status": "COMPLETE",
"remaining": [
"docs"
]
}{
"valid": false,
"diagnostics": [
{
"code": "COMPLETE_WITH_REMAINING",
"severity": "ERROR",
"message": "COMPLETE cannot carry remaining work.",
"path": "/remaining",
"source": "squillify",
"details": {}
}
],
"completeness": {
"completedCount": 0,
"remainingCount": 1,
"artifactCount": 0,
"blockerCount": 0,
"hasNextAction": false
},
"status": "COMPLETE"
}Recommended use cases
- Refuse COMPLETE packets that still list remaining work
- Require a blocker before a BLOCKED packet is accepted
Avoid for
- Creating or routing the handoff
- Checking artifact access
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.