> ## Documentation Index
> Fetch the complete documentation index at: https://docs.chappiesdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Harnesses: Ground ChatGPT in Your App's Full Context

> A harness grounds the model in your app's identity, capabilities, and tools — applied automatically at the start of every conversation.

A harness is the first thing the model sees in every conversation your app starts. It declares who you are, what your app surface can do, and which tools the model is allowed to call. Without a harness, the model has no idea whether it's running inside a photo editor, an inventory tracker, or a general-purpose chat shell. By providing one, you prevent the model from inventing capabilities you haven't enabled and stop it from presenting itself as a different Codex surface.

## What a Harness Contains

A `ChappieHarness` value packages six fields. The SDK applies this context automatically at the start of every conversation so you don't have to manage it manually.

<ParamField path="name" type="String" default="Chappie iOS Harness">
  A display name that identifies this harness. The model uses it to refer to the current surface.
</ParamField>

<ParamField path="summary" type="String" default="A native iOS assistant harness that streams model turns through app-owned context.">
  A one-line description of what the app surface does. Keep it short and factual.
</ParamField>

<ParamField path="instructions" type="String" default="ChappieHarness.defaultInstructions">
  System-level instructions appended to every request. The SDK ships a default guardrail that prevents the model from claiming to be the Codex desktop app or accessing undeclared capabilities. Override this only if you have a good reason to replace the built-in guardrail entirely.
</ParamField>

<ParamField path="capabilities" type="[String]" default="[&#x22;multi-turn transcript&#x22;, &#x22;streaming responses&#x22;, &#x22;model selection&#x22;, &#x22;usage-limit awareness&#x22;]">
  A list of plain-English strings that tell the model what the host app has wired up. The model will only claim to support capabilities that appear here.
</ParamField>

<ParamField path="tools" type="[ChappieHarnessTool]" default="[]">
  Declared tools the model can call. Each entry names a function and describes what it does. Register tool handlers separately via `ChappieHostTool` — the harness declaration is the model-facing manifest; the host tool is the Swift handler that runs it.
</ParamField>

<ParamField path="plugins" type="[ChappieHarnessPlugin]" default="[]">
  Declared plugins available in this surface. Each plugin has a `name`, `description`, and optional `version`.
</ParamField>

## The Default Harness

`ChappieHarness.default` is a ready-made harness that works for general-purpose assistant surfaces. It carries the built-in guardrail instructions, four standard capabilities (`multi-turn transcript`, `streaming responses`, `model selection`, `usage-limit awareness`), and empty tool and plugin lists. Use it whenever you don't need to customise the context.

```swift theme={null}
// These two lines are equivalent:
let client = Chappie.client()
let client = Chappie.client(harness: .default)
```

## Creating a Custom Harness

Declare a harness that matches your app's actual surface, then pass it to `Chappie.client(harness:)`.

```swift theme={null}
let harness = ChappieHarness(
    name: "Inventory Harness",
    summary: "Native iOS surface for inventory questions and app context.",
    capabilities: [
        "multi-turn transcript",
        "streaming responses"
    ]
)
let client = Chappie.client(harness: harness)
```

For rapid prototyping, you can pass a raw string literal. The SDK wraps it in an `"Inline Harness"` with no declared capabilities or tools.

```swift theme={null}
// String literal — good for quick experiments
let pirateClient = Chappie.client(harness: "You're a pirate. Speak like it.")

// Full default harness
let defaultClient = Chappie.client(harness: .default)
```

<Note>
  `ChappieHarness.none` is a harness with all fields empty. It disables harness injection entirely, which means the model receives no surface context. Use it only in test scenarios where you want a completely clean transcript.
</Note>

## Ready-Made Sample Harnesses

`ChappieHarnessSamples` ships four harnesses you can use directly or adapt as starting points:

<CardGroup cols={2}>
  <Card title=".currentScreen" icon="display">
    Declares `read_current_screen` — returns app-provided text and state for the currently visible screen. Useful for context-aware in-app assistance.
  </Card>

  <Card title=".documents" icon="file-lines">
    Declares `read_selected_document_text` — returns the user-selected document text and lightweight metadata. Built for document editing surfaces.
  </Card>

  <Card title=".photos" icon="image">
    Declares `describe_selected_photo` — returns app-provided metadata or a safe description for the selected photo. Scoped to app-owned assets only.
  </Card>

  <Card title=".inventory" icon="boxes-stacked">
    Declares `lookup_item` — looks up one inventory item by SKU. A good starting point for retail or warehouse apps.
  </Card>
</CardGroup>

Use them like any other harness value:

```swift theme={null}
let client = Chappie.client(harness: ChappieHarnessSamples.inventory)
```

## Declaring Tools in a Harness

When you want the model to be able to call a function your app implements, add a `ChappieHarnessTool` entry to the harness and register the matching Swift handler when you create the client. The harness declaration tells the model what the tool does; the host tool provides the runtime implementation.

```swift theme={null}
let harness = ChappieHarness(
    name: "Inventory Harness",
    summary: "Native iOS surface for inventory questions and app context.",
    capabilities: [
        "multi-turn transcript",
        "streaming responses",
        "inventory lookup"
    ],
    tools: [
        ChappieHarnessTool(
            name: "lookup_item",
            description: "Looks up one inventory item by SKU."
        )
    ]
)

let client = Chappie.client(
    harness: harness,
    tools: [
        ChappieHostTool(name: "lookup_item") { arguments in
            // Return a result string based on arguments
            return lookupItem(sku: arguments["sku"] as? String ?? "")
        }
    ]
)
```

<Tip>
  Keep `ChappieHarnessTool.description` concise and action-oriented. The model uses it to decide when and whether to call the tool, so a clear description produces more reliable calling behaviour.
</Tip>

For full details on registering handlers, providing approval flows, and handling tool errors, see the **Host Tools** guide.
