ModelWorks logoModelWorks

Outputs

Define and use circuit-level and step-level outputs in ModelWorks

Outputs

ModelWorks circuits can expose results at two levels:

  1. Circuit-level Outputs: Defined at the bottom of your circuit to expose final results or aggregated data to callers.
  2. Step-level Outputs: Intermediate values produced by individual steps, which can be referenced within the circuit.

Circuit-level Outputs

Circuit-level outputs live under the top-level outputs key in your circuit definition. They map variables from any step into the final result object that callers receive.

PropertyDescription
nameIdentifier for the output
descriptionHuman-readable explanation of the output
valueExpression referencing a step’s output (e.g., ${{ stepName.output.foo }})

Example in JSON:

JSON
"outputs": [
  {
    "name": "chat_completion_output",
    "description": "The generated chat message stream",
    "value": "${{ chat_completion_response.output.stream_accumulators.delta_accumulator }}"
  }
]

When the circuit finishes, its response payload will include:

JSON
{
  "chat_completion_output": "<full concatenated response>"
}

Step-level Outputs

Each primitive step returns its own output object containing fields specific to that function. You can reference these outputs in downstream steps or in your circuit-level outputs.

For example, the Runway Gen-3 Video Generation circuit:

JSON
{
  "steps": [
    {
      "name": "runway_video_generation",
      "function": "circuit.core.fetch",
      "input": { /* ... */ },
      "outputs": [
        {
          "name": "runway_job_id",
          "description": "ID for polling video status",
          "value": "${{ runway_video_generation.output.json_body.id }}"
        }
      ]
    }
  ],
  "outputs": [
    {
      "name": "video_url",
      "description": "Final video URL",
      "value": "${{ fetch_video_url.output.json_body.output.$.[0] }}"
    }
  ]
}

Here:

  • runway_video_generation.output.json_body.id is a step-level output capturing the job ID.
  • Downstream steps can consume ${{ runway_job_id }} or their own output fields.
  • The final circuit output video_url aggregates a value from the last step.

For full details on each primitive’s available output fields, see the Primitive Outputs Reference.


Excluding Step Outputs from Results

By default, every step's raw output ({"output": result}) is included in the final result that callers receive. This is useful for debugging and transparency, but sometimes a step's raw output contains sensitive data (like API keys in response headers) or large intermediate payloads that shouldn't be exposed.

Set include_in_outputs: false on any step to exclude its raw output from the final result while keeping it available to downstream steps via selectors.

How It Works

include_in_outputsRaw output in resultAvailable to downstream steps
true (default)YesYes
falseNoYes

The flag only gates the raw step output — the {"output": result} object written to the result. It does not affect:

  • Step-level outputs[] — declared outputs are always included regardless of this flag
  • Circuit-level outputs[] — top-level circuit outputs are always included
  • Memory — the step's output is always inserted into memory and can be referenced by downstream selectors

Use Case: Hiding Sensitive Intermediate Responses

A fetch step returns a response containing an API key in its headers. A downstream transform step extracts only the needed field. Set include_in_outputs: false on the fetch step so the raw response (with the key) stays out of the result, while the transform's clean output is included:

JSON
{
  "steps": [
    {
      "name": "fetch_auth_token",
      "function": "circuit.core.fetch",
      "include_in_outputs": false,
      "input": {
        "url": "https://api.example.com/auth",
        "method": "POST",
        "body": { "client_id": "${{ secrets.client_id }}" }
      }
    },
    {
      "name": "extract_token",
      "function": "circuit.core.transform.json",
      "input": {
        "source": "${{ fetch_auth_token.output.json_body }}",
        "operations": [
          { "type": "get", "path": "access_token" }
        ]
      }
    }
  ],
  "outputs": [
    {
      "name": "token",
      "value": "${{ extract_token.output }}"
    }
  ]
}

In this example:

  • fetch_auth_token runs and its output goes into memory — downstream steps can access ${{ fetch_auth_token.output.json_body }}
  • The raw fetch response (headers, full body) is excluded from the result
  • extract_token runs and its output is included in the result (default behavior)
  • The circuit-level token output references the transform result — always included

Default Behavior (Backward Compatible)

If you omit include_in_outputs entirely, the step behaves as if include_in_outputs: true was set — the raw output appears in the result. Existing circuits work exactly as before.


Next up: Triggers – learn how to schedule your circuits or respond to external events!

On this page

On this page