# How to Extract String Output from Agent Responses Using `Output.string()` in Sandcastle

> Learn how to extract string output from agent responses with Output.string() in Sandcastle. Easily get plain text from custom tags as a JavaScript string.

- Repository: [Matt Pocock/sandcastle](https://github.com/mattpocock/sandcastle)
- Tags: how-to-guide
- Published: 2026-05-24

---

**Use `Output.string()` to declare that an agent should emit plain text wrapped in custom XML-style tags, and Sandcastle will automatically extract, trim, and return that content as a JavaScript string.**

The Sandcastle library (`mattpocock/sandcastle`) provides a structured output API for reliably parsing agent responses without manual string manipulation. When you need to capture free-form text, code snippets, or any content that doesn't require JSON schema validation, `Output.string()` offers a lightweight mechanism to extract raw string data from the agent's stdout using declarative XML-style tags.

## Declaring String Output with `Output.string()`

According to the Sandcastle source code in [`src/Output.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Output.ts), the `Output.string()` method creates an output definition that instructs the framework to look for a specific tag name in the agent's response. The method accepts a configuration object with a `tag` property, which defines the literal XML-style tag that must enclose the desired output.

```typescript
import { Output } from "@ai-hero/sandcastle";

// Declare that the agent should wrap its response in <summary> tags
const stringOutput = Output.string({ tag: "summary" });

```

As implemented in [`src/Output.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Output.ts) (lines 14–18), this creates an `OutputStringDefinition` with an internal `_tag` property set to `"string"`. Unlike structured object outputs, this definition performs no JSON parsing or schema validation, making it ideal for unstructured text extraction.

## How the Extraction Pipeline Works

The string extraction process involves three distinct phases: prompt validation, stdout collection, and content extraction. Single-iteration runs are required for structured output in Sandcastle.

### Validating the Prompt Tag

Before executing the sandbox, Sandcastle validates that the prompt contains the opening tag defined in the output configuration. In [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) (lines 96–100), the framework checks for the presence of `<${tag}>` in the resolved prompt string. If the tag is missing, `run()` throws an error immediately, preventing execution of a prompt that cannot satisfy the output contract.

```typescript
// Example prompt that satisfies the validation
const prompt = `
You are a helpful assistant. Summarize the outcome and wrap it in <summary> tags.

<summary>
</summary>
`;

```

### Collecting Agent Output

During execution, Sandcastle collects the agent's stdout across all iterations. As noted in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) (lines 60–66), the framework aggregates output from the sandbox process. For structured output extraction, the system operates on the complete stdout buffer after the agent finishes execution.

### Extracting and Trimming the String

The extraction logic resides in [`src/extractStructuredOutput.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/extractStructuredOutput.ts). When processing a string-type output definition (lines 24–36), the framework delegates to the `extractString()` helper function (lines 86–92).

The extraction process follows these steps:

1. **Locate the last occurrence**: The `findLastTagContent()` function (lines 12–34) scans the entire stdout buffer and identifies the **last** occurrence of the specified `<tag>…</tag>` pair. This allows agents to include multiple outputs or logging while ensuring the final tagged content is captured.

2. **Extract inner content**: The function extracts the text content between the opening and closing tags.

3. **Trim whitespace**: As implemented in lines 94–101, the raw extracted content undergoes a `trim()` operation to remove leading and trailing whitespace, including newlines and indentation introduced by the agent.

4. **Error handling**: If the closing tag is absent or malformed, the extraction throws a `StructuredOutputError`, which bubbles up from the `run()` function to alert callers that the output contract was violated.

## Practical Implementation Example

The following example demonstrates a complete implementation using `Output.string()` to extract a summary from an agent:

```typescript
import { run, Output } from "@ai-hero/sandcastle";

const prompt = `
You are a helpful assistant. Summarize the outcome of the computation
and wrap the summary in <summary> tags.

<summary>
</summary>
`;

async function main() {
  const result = await run({
    sandbox: { tag: "docker", env: {} },
    prompt,
    output: Output.string({ tag: "summary" }),
  });

  // result.output is a plain string: "The calculation finished successfully in 12ms."
  console.log("Agent summary:", result.output);
}

```

The agent must emit output matching the declared tag structure:

```

... other stdout ...
<summary>
The calculation finished successfully in 12ms.
</summary>

```

Sandcastle locates the last `<summary>` block, trims the newline and indentation, and exposes the clean string via `result.output`.

## Summary

- **`Output.string()`** declares a string-type output in [`src/Output.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/Output.ts) that captures plain text without JSON parsing.
- The **prompt must contain the opening tag**, validated in [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) (lines 96–100), or execution fails immediately.
- **Stdout collection** happens across the run lifecycle ([`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts), lines 60–66), with extraction occurring after the agent completes.
- **Last-tag matching** in [`src/extractStructuredOutput.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/extractStructuredOutput.ts) (lines 12–34) ensures the final occurrence of the tag is extracted, supporting verbose agent output.
- **Automatic trimming** removes whitespace from the extracted content before returning the JavaScript string.
- **StructuredOutputError** is thrown if the tag is missing or malformed, providing clear error boundaries.

## Frequently Asked Questions

### What is `Output.string()` used for?

`Output.string()` is designed for extracting free-form text, code snippets, or natural language responses that don't fit a strict JSON schema. According to the Sandcastle implementation, it bypasses JSON parsing and validation, returning the raw string content directly. This makes it ideal for capturing summaries, explanations, or generated code where wrapping the content in XML-style tags is more reliable than parsing unstructured stdout.

### How does Sandcastle handle multiple occurrences of the same tag?

When multiple instances of the declared tag appear in the stdout, Sandcastle extracts the **last** occurrence. The `findLastTagContent()` function in [`src/extractStructuredOutput.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/extractStructuredOutput.ts) (lines 12–34) performs a reverse search through the output buffer. This behavior allows agents to output debugging information or previous attempts while ensuring the final tagged block is captured as the authoritative response.

### What happens if the agent doesn't include the required tag?

If the opening tag is missing from the prompt, `run()` throws an error during validation ([`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts), lines 96–100). If the agent fails to output the closing tag during execution, the extraction phase throws a `StructuredOutputError` ([`src/extractStructuredOutput.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/extractStructuredOutput.ts), lines 94–98). Both errors bubble up to the caller, allowing you to implement retry logic or error handling for malformed agent responses.

### Can I use `Output.string()` with multi-iteration runs?

No. According to the source code analysis of [`src/run.ts`](https://github.com/mattpocock/sandcastle/blob/main/src/run.ts) (lines 60–66), structured output extraction requires single-iteration runs. The framework validates this constraint because the extraction logic assumes a complete stdout buffer collected from a single execution context. Attempting to use structured output with multi-iteration configurations will result in validation errors or undefined behavior.