Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Agent Step Result Normalizer

agent.step_result_normalize

ProductionBounded custom (Class B)Deterministicstrictinstantv1.0.0
No network

Overview

This advises and does not act: it reshapes a result you already have and calls nothing. Whatever a step returned — an object, an array, a bare string, a number, null — comes back as the same envelope, so an agent branches on one shape instead of one shape per tool. Status is derived by published rules for the profile you pick, and it is never guessed upwards: a payload the profile does not recognise becomes unknown, because inferring success is exactly how an agent carries on after a step that failed. Every ceiling is applied while walking the payload rather than after copying it, so a 2 MB result never becomes a 2 MB envelope, and each reduction is flagged so you know the envelope is partial. redactKeys removes values by exact field name as a convenience for names you already know; it is not a scanner, and security.detect_secrets and security.redact_secrets are the skills for that.

An agent that branches on each tool's own result shape grows a special case per tool, and the worst of those special cases is the one that reads an unfamiliar payload as success and carries on. One envelope with a status that falls back to unknown removes both problems, and bounding the payload keeps a large result from filling the context window.

Reliability

Fully deterministic: the same payload and the same ceilings always produce the same envelope, and field order inside the payload is preserved. Status never rises on a guess — an unrecognised payload is unknown, not success. Failures: RESULT_PAYLOAD_TOO_LARGE means the payload serialises past 2000000 characters, which is the most one request body can carry it in — bound it at the source before sending it; RESULT_PROFILE_UNSUPPORTED means profile named something outside the five published values, and an unknown profile is refused rather than treated as the default — correct the name and retry; RESULT_LIMITS_INVALID means maxTextChars, maxItems, maxDepth, stepId or tool fell outside its published range — bring the value inside the range and retry; RESULT_OUTPUT_TOO_LARGE means the envelope itself would pass 262144 characters at the ceilings you chose, which needs a very high maxTextChars — lower maxTextChars or maxItems and retry; RESULT_REDACT_KEYS_INVALID means redactKeys held more than 200 names, a non-string entry, or an entry longer than 256 characters — fix the list and retry.

Context footprint

The envelope is bounded by construction: with the defaults it stays in single-digit kilobytes no matter how large the payload was, and it can never pass 262144 characters. metrics.payloadChars records the original size so you can see how much was left behind. A successful call costs 1 execution credit.

When to use it

Immediately after a step returns, before the result reaches the agent's branching logic or its prompt.

When the payload must survive intact, or when the real requirement is removing secrets rather than shaping a result.

Scope

Note
Reshape one supplied tool result into a fixed, bounded envelope with a derived status, flagging every reduction it had to make.

Non-goals

  • Does not call the tool that produced the payload, or any other tool
  • Does not scan for secrets or personal data — redactKeys matches names only
  • Does not repair a malformed payload, only describe and bound it
  • Does not infer success from a payload its profile cannot read
  • Does not keep or cache the payload after the answer is returned

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

normalization

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input2 MB

How we handle your data

Sensitive output possible
What this means

This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.

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 may contain submitted or transformed 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.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
toolResultobjectYesOpaque tool payload accepted as any JSON value including null; send the field even when its value is null.
profilestringNoStatus-derivation profile; omit it for SQUILLIFY. Published values: SQUILLIFY, HTTP, ERROR_ENVELOPE, GENERIC, TEXT. An unrecognised profile is RESULT_PROFILE_UNSUPPORTED.
stepIdstringNoBounded correlation or tool label copied into the envelope unchanged; omit it when unused.
toolstringNoBounded correlation or tool label copied into the envelope unchanged; omit it when unused.
maxTextCharsintegerNoString ceiling applied while walking; omit it for 4000.
maxItemsintegerNoArray-entry ceiling applied while walking; omit it for 50.
maxDepthintegerNoWalk depth ceiling applied while walking; omit it for 6.
includeRawbooleanNoWhether a fitting serialised payload is echoed; omit it for false.
redactKeysarrayNoBounded array of 0 through 200 exact field names to redact; omit it for none.

Output schema

FieldTypeRequiredDescription
statusstringYesDerived envelope status, never guessed upwards to success.
stepIdstringNoCopied correlation id, present only when you supplied one.
toolstringNoCopied tool name, present only when you supplied one.
summarystringYesOne-line shape summary of the bounded payload.
dataobjectYesBounded object projection of the payload; additional properties preserve remaining fields after ceilings — unconstrained RFC 8259 JSON items.
textstringNoExtracted textual content, present only when the payload or a recognised field holds text.
itemsarrayYesBounded collection projection of 0 through 1000 items taken from the payload or a recognised collection field.
errorobjectNoClosed normalized error data with a stable code and optional message; its presence does not make this successful normalization invocation fail.
metricsobjectYesClosed payload-size metrics captured before truncation, with payloadChars, depth and itemCount.
truncationobjectYesClosed truncation flags naming every ceiling that actually cut the envelope.
profilestringYesResolved profile that decided the status, in lower case.
rawstringNoSerialised payload, present only when includeRaw is true and it fits maxTextChars.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"agent.step_result_normalize","input":{"toolResult":{"slug":"weekly-report"},"profile":"SQUILLIFY"}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("agent.step_result_normalize", {"toolResult":{"error":{"message":"The file reference is not accessible with the current credentials.","code":"FILE_REF_NOT_ACCESSIBLE"},"requestId":"req-8813"},"redactKeys":["requestId"],"stepId":"s-3","tool":"file.read"});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
RESULT_PAYLOAD_TOO_LARGE429NoA size, quota, rate, or time limit was exceeded.
RESULT_PROFILE_UNSUPPORTED400NoThe request payload failed this skill's input validation.
RESULT_LIMITS_INVALID400NoThe request payload failed this skill's input validation.
RESULT_OUTPUT_TOO_LARGE429NoA size, quota, rate, or time limit was exceeded.
RESULT_REDACT_KEYS_INVALID400NoThe request payload failed this skill's input validation.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Does not call the tool that produced the payload, or any other tool
  • Does not scan for secrets or personal data — redactKeys matches names only
  • Does not repair a malformed payload, only describe and bound it
  • Does not infer success from a payload its profile cannot read
  • Does not keep or cache the payload after the answer is returned
  • Removing secrets or personal data before storage
  • Keeping a payload intact — this deliberately bounds and drops
  • Deciding what to do next, which is the agent's job

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "agent.step_result_normalize",
  "input": {
    "toolResult": {
      "error": {
        "message": "The file reference is not accessible with the current credentials.",
        "code": "FILE_REF_NOT_ACCESSIBLE"
      },
      "requestId": "req-8813"
    },
    "redactKeys": [
      "requestId"
    ],
    "stepId": "s-3",
    "tool": "file.read"
  }
}

Examples

A platform result with a nested error envelope, normalised to status error

Inputjson
{
  "toolResult": {
    "error": {
      "message": "The file reference is not accessible with the current credentials.",
      "code": "FILE_REF_NOT_ACCESSIBLE"
    },
    "requestId": "req-8813"
  },
  "redactKeys": [
    "requestId"
  ],
  "stepId": "s-3",
  "tool": "file.read"
}
Expected outputjson
{
  "status": "error",
  "stepId": "s-3",
  "data": {
    "error": {
      "message": "The file reference is not accessible with the current credentials.",
      "code": "FILE_REF_NOT_ACCESSIBLE"
    },
    "requestId": "<removed>"
  },
  "metrics": {
    "payloadChars": 146,
    "depth": 2,
    "itemCount": 0
  },
  "truncation": {
    "textTruncated": false,
    "itemsTruncated": false,
    "depthTruncated": false,
    "fieldsDropped": 0
  },
  "tool": "file.read",
  "items": [],
  "summary": "2 fields",
  "error": {
    "code": "FILE_REF_NOT_ACCESSIBLE",
    "message": "The file reference is not accessible with the current credentials."
  },
  "profile": "squillify"
}
Tip
The SQUILLIFY profile reads error.code, so the status is error and the code and message are lifted into the envelope's error field.

An HTTP 404 mapped to client_error, with the correlation fields copied through

Inputjson
{
  "toolResult": {
    "body": {
      "invoice": "inv-9912",
      "code": "NOT_FOUND"
    },
    "statusCode": 404,
    "message": "No such invoice"
  },
  "stepId": "s-7",
  "tool": "billing.fetch_invoice",
  "profile": "HTTP"
}
Expected outputjson
{
  "data": {
    "body": {
      "invoice": "inv-9912",
      "code": "NOT_FOUND"
    },
    "statusCode": 404,
    "message": "No such invoice"
  },
  "summary": "3 fields, 15 characters of text",
  "truncation": {
    "textTruncated": false,
    "itemsTruncated": false,
    "depthTruncated": false,
    "fieldsDropped": 0
  },
  "status": "client_error",
  "tool": "billing.fetch_invoice",
  "error": {
    "code": "HTTP_CLIENT_ERROR",
    "message": "No such invoice"
  },
  "stepId": "s-7",
  "text": "No such invoice",
  "profile": "http",
  "metrics": {
    "payloadChars": 95,
    "depth": 2,
    "itemCount": 0
  },
  "items": []
}
Tip
A 4xx becomes client_error and a 5xx becomes server_error, so an agent can tell a bad request from an outage without parsing the payload.
  • Give an agent loop one result shape to branch on across many tools
  • Cut a multi-megabyte tool result down to something a prompt can hold
  • Turn a raw HTTP response into a status an agent can act on

Avoid for

  • Removing secrets or personal data before storage
  • Keeping a payload intact — this deliberately bounds and drops
  • Deciding what to do next, which is the agent's job

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.

Tags

envelopeagentnormalizationtransformationjson