Skip to main content
A ChappiePluginManifest is a packaging type for a reusable harness bundle. It wraps a base ChappieHarness together with additional tool descriptors, plugin descriptors, and arbitrary setup metadata — all in a single Codable value you can store, share, or load from JSON. When you’re ready to create a client, call manifest.resolvedHarness to merge everything into a single ChappieHarness with duplicates removed.

Create and use a plugin manifest

let manifest = ChappiePluginManifest(
    identifier: "com.example.inventory",
    displayName: "Inventory Assistant",
    summary: "Inventory lookup and replenishment helpers.",
    version: "0.1.0",
    harness: ChappieHarnessSamples.inventory
)

let client = Chappie.client(harness: manifest.resolvedHarness)
let reply = try await client.send("How much stock is left for SKU-456?")
resolvedHarness merges the manifest’s tools and plugins arrays into the base harness, deduplicating tools by name (first occurrence wins). The returned ChappieHarness is a plain value with no reference back to the manifest, so you can mutate or extend it further before passing it to the client.

Manifest fields

identifier
String
required
A reverse-DNS bundle identifier that uniquely names this manifest, for example "com.example.inventory". Use it as a stable key when storing or referencing manifests across builds.
displayName
String
required
A human-readable name shown in debug surfaces and logs, for example "Inventory Assistant".
summary
String
required
A short description of what the manifest’s harness covers. This text is not sent to the model directly — it lives in the manifest layer for documentation and tooling purposes.
version
String?
A semver string such as "0.1.0". Optional, but useful when you distribute manifests as versioned packages or store them in a registry.
harness
ChappieHarness
required
The base harness. All tools and plugins from tools and plugins arrays are merged into this harness when you call resolvedHarness.
tools
[ChappieHarnessTool]
Additional tool descriptors merged into the harness at resolution. Any tool whose name already exists in harness.tools is silently dropped — the harness definition takes precedence.
plugins
[ChappieHarnessPlugin]
Additional plugin descriptors appended to the harness at resolution. Unlike tools, plugins are not deduplicated by name.
setupMetadata
[String: ChappieJSONValue]
A free-form dictionary for arbitrary metadata your app needs at setup time — API endpoints, feature flags, configuration values, and so on. The model never sees this directly; it’s available to your own code after you decode the manifest.

Add extra tools and plugins at manifest creation

Pass tools and plugins to the manifest initializer to augment the base harness without modifying it:
let manifest = ChappiePluginManifest(
    identifier: "com.example.fulfillment",
    displayName: "Fulfillment Suite",
    summary: "Order creation, tracking, and cancellation flows.",
    version: "1.2.0",
    harness: ChappieHarnessSamples.inventory,
    tools: [
        ChappieHarnessTool(
            name: "create_order",
            description: "Creates a new purchase order for a given SKU and quantity.",
            inputSchema: .object([
                "type": .string("object"),
                "properties": .object([
                    "sku": .object(["type": .string("string")]),
                    "quantity": .object(["type": .string("number")])
                ]),
                "required": .array([.string("sku"), .string("quantity")]),
                "additionalProperties": .bool(false)
            ])
        )
    ],
    plugins: [
        ChappieHarnessPlugin(
            name: "fulfillment-workflows",
            description: "Multi-step order creation and cancellation workflows.",
            version: "1.0.0"
        )
    ],
    setupMetadata: [
        "api_base_url": .string("https://api.example.com/v2"),
        "max_order_qty": .number(500)
    ]
)

let client = Chappie.client(harness: manifest.resolvedHarness)

ChappieHarnessPlugin fields

Plugin descriptors give the model awareness of named workflow plugins available in the harness. They are purely declarative — the model can reference them in reasoning, but runtime plugin execution APIs are coming in a future release.
name
String
required
A unique, machine-readable plugin identifier, for example "fulfillment-workflows".
description
String
required
A short, human-readable description of what the plugin does. The model sees this in the harness manifest.
version
String?
An optional semver string for the plugin, for example "1.0.0".

Built-in sample harnesses

ChappieHarnessSamples provides ready-made harnesses for common app surfaces. Use them as the harness base in a manifest or pass them directly to Chappie.client(harness:):

.currentScreen

Declares a read_current_screen tool. Use it in assistants that need to answer questions about the currently visible UI state.

.documents

Declares a read_selected_document_text tool. Use it for summarization, rewriting, and structured extraction flows.

.photos

Declares a describe_selected_photo tool. Use it when the assistant should reason about user-selected photo metadata.

.inventory

Declares a lookup_item tool. Use it as the starting point for inventory lookup and replenishment conversations.

Serialize and deserialize manifests

ChappiePluginManifest conforms to Codable, so you can round-trip it through JSON. Store manifests in your app bundle, fetch them from a server, or cache them to disk — then decode and resolve them at runtime.
// Encode to JSON
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let data = try encoder.encode(manifest)

// Decode from JSON
let decoded = try JSONDecoder().decode(ChappiePluginManifest.self, from: data)
let client = Chappie.client(harness: decoded.resolvedHarness)
This makes manifests a natural interchange format: ship a manifest.json in your app bundle for default configurations, or serve environment-specific manifests from your backend without recompiling your app.