Skip to main content

Reuse thunk interfaces and plug-in connections

Export a thunk's tool signatures as an interface, require that interface as a plug-in connection, or create an MCP server that implements it

An interface is the list of tools a thunk advertises — each tool's name, description, inputs, and output — with no implementation attached. The inputs and output are described in Thunk property types, the same types you use for a tool's inputs and a workflow's properties: Text, Number, Date, File, JSON Object, a Structure Type, or a list of any of them. Another thunk can require those tools without naming who provides them. A third thunk can be created from the same file so it starts with those tools already stubbed out.

This is different from publishing a thunk as an MCP server for an external AI assistant, and from importing another thunk as a tool library. Those both bind you to one specific thunk. An interface lets you write against a contract, then plug in any connection that matches it. For when to put a system behind an interface, and when to choose an implementation per work item, see How to use modularity effectively when building a thunk.

There are three things you can do with an interface:

  1. Export one from a thunk that already has tools.

  2. Require one as a plug-in connection on another thunk.

  3. Implement one by creating an MCP server from the file.

Export an interface

On a thunk that already has tools, open Admin → Deploy → Export and go to the Export Interface tab. Choose the name, description, and tools an outside caller should see, the same way you would when publishing the thunk as an MCP server.

The same tab has Download interface file and Copy to clipboard. The file is JSON: a name, a version, a description, and the tool signatures you turned on. Share it with whoever is building the calling thunk. Check against an interface compares this thunk's published tools to a file someone else depends on, so you can see a mismatch before they try to bind.

The file describes only the tools that are switched on for export. A tool you left unchecked is not in the contract. A tool whose inputs can't be described in property types — for example an input that accepts either a number or a text value — is left out too, and the tab names it and says why.

Exporting the file does not turn the MCP server on. Publishing is a separate switch on the Enabled/Disabled tab.

Require an interface — a plug-in connection

A plug-in connection is a parameter of this thunk: a name plus the tools whatever is plugged in must provide. The thunk's steps call those tools through the name, so you can change the connection behind it later without rewriting the workflow.

Plug-in connections live on the thunk, not on your account. You do not create them under Account → Connections. Open the thunk's Connections pane, select Add Connection, and choose New plug-in connection….

  1. Give it a Name — how this thunk will refer to the connection, for example CRM.

  2. Set the interface: select Define interface… to write it here, choose an interface file, or pick a connection whose current tools should become the contract.

  3. Optionally bind it now to an environment connection that provides exactly those tools. You can leave it unbound and bind it later from the connection's detail view.

Define interface… opens an editor with the interface's name, version, and description, and one entry per tool. For each tool, give a name and a description, then add its inputs in the same property editor you use for a custom tool's inputs. Select Declare an output to describe what the tool returns. An input can be a JSON Object, or take the shape of one of this thunk's Structure Types or the type of one of its properties. Those are copied into the interface as the type they have now, so the interface stands on its own when another thunk uses it.

Open a plug-in connection from the Connections pane to see three sections: Interface, Binding, and Tools. Interface and Binding start collapsed. Select a section's header to open it.

  • Interface shows the contract the connection requires. Collapsed, it shows the interface's name and version. Open it to see how many tools the interface has. View interface shows each tool's description, inputs, and output as property types (switch on Show JSON to see the file's JSON instead), and Export to file saves the interface as a file you can share. Thunk owners and admins also see Change interface….

  • Binding shows which connection currently provides the interface. Collapsed, it shows the default connection, and Dynamic with a count when the binding also picks a different connection for particular values. If the binding has a problem, such as a connection that no longer matches, the header says so. Open it to pick a different connection. The list only offers connections that match. If nothing is bound yet, Binding starts open.

  • Tools lists the interface's tools, the same as for any other connection.

To require a different interface, select Change interface…, then Edit interface… to change it in the editor, or choose an interface file. When you edit it, the editor suggests the next version number from what you changed: a new major version when a tool is removed or its inputs or output change, a new minor version when a tool is added, and a patch when only descriptions change. You can type a different one. Before anything changes, Thunk lists the tools the new interface adds, removes, and changes, and tells you whether the current binding still matches. If it does not, the connection is unbound, and you bind it again to a connection that matches. The plug-in name stays the same, so steps keep calling the tools both interfaces share. New tools are turned on; steps lose any tool the new interface removes.

To delete a plug-in connection, select Remove on its row in the Connections pane. Its interface is deleted with it, so export the interface first if you want to keep a copy.

The thunk's agent sees the tools under names that include the plug-in name (find_account_crm). Rebinding to a different matching connection does not rename them.

Matching is exact on names and inputs. The bound connection must expose each required tool with the same name and the same inputs: the same input names, property types, and which ones are required. Types are compared as property types, not as text, so a connection that describes the same types in its own way — for example a whole-number input where the interface says Number — still matches, including a third-party MCP server. Extra tools on the provider are fine. A renamed tool or input is not — the plug-in connection then contributes no tools, rather than a different set of tools than the one you designed against.

Outputs are matched too, when the interface declares them. A provider tool must declare an output that has every field the interface's output lists, with the same property types, and the fields the interface requires must be required there too. A provider tool that declares no output does not match one that does. A tool whose interface entry declares no output promises nothing about what it returns, so declare the output of every tool whose result a step or a custom tool reads; otherwise a connection can match the interface and still return different fields.

Descriptions don't have to match. The provider can word a tool's description, or any input's description, differently from the interface. Your thunk's agent reads the provider's wording.

The one allowance is for objects, whether a JSON Object or a Structure Type. Anywhere the interface has an object — an input, a result, or an item in a list — the provider's object may have more fields than the interface lists. A Salesforce-backed provider can return its own owner and region fields alongside the ones the interface names, or ask for an extra field in an input object. A provider built in Thunk can use one of its own Structure Types there: an interface account object with name and id fields is matched by the provider's SalesforceAccount type with name, id, owner, and region. Everything else must match exactly, apart from descriptions: which inputs each tool takes, and every value that is not an object.

Your thunk's agent works with the provider it is bound to, not with the interface. It gets a richer result's extra fields as ordinary fields, and when the provider's tool asks for an extra input field, the agent is asked for it too. If a call doesn't include a field the provider requires, the call fails with an error naming that field.

Requests that come in several shapes

A thunk often handles several kinds of request through one plug-in connection, for example expense receipts and card-limit increases, and each kind needs different fields. An interface can't declare one input that takes a different shape for each kind: a tool whose input could be one of several shapes is left out of the interface. A JSON Object input that lists every kind's fields next to a request-type field doesn't solve it either, because it can't make a field required for one kind and not for another.

Give each kind of request its own tool instead:

  1. Define a Structure Type for each kind, such as ExpenseReceipt and CardLimitIncrease. Every field of a Structure Type is required, so each kind's own fields are enforced.

  2. Put the fields every kind shares, such as the requester and the amount, in a Structure Type of their own, such as RequestDetails, and use it as a field of each kind's type.

  3. Give the interface one tool per kind, such as submit_expense_receipt and request_card_limit_increase, each taking that kind's Structure Type as its input. Declare each tool's output.

  4. Record the kind of request on the work item, for example in a Request type column; the step's enabled tools then resolve which one runs.

A provider then implements each tool with that kind's fields, and a call that leaves out one of them fails with an error naming the field. If a different provider handles each kind, give each kind its own plug-in connection and interface, so each provider implements only the tools for its kind.

Keep a result in the provider's shape

To store a plug-in tool's result in your workflow with all of its fields, give the property the Reference type and pick a tool position as its Reference target — for example CRM › get_account › output.account. The list shows every position in the plug-in connection's tools that a property can hold, next to the thunk's columns. The property then takes whatever type the connected tool has there.

The type follows the binding. While a step runs, the property has the shape of the connection bound for that step, so each work item keeps the fields of the connection that produced it. If a later step bound to a different connection updates a single object (not a list), the stored fields that connection doesn't know about are kept. Everywhere else — the table, the property editor, and exports — shows the shape of the default binding.

If a third-party MCP server's tools do not match the interface — different tool names or arguments — do not loosen the contract. Create an adapter: an MCP server from the same interface file whose tool bodies call the physical server. Bind the plug-in connection to the adapter.

A plug-in connection is a connection like any other at the step level. After you add it, enable or narrow it on a step the same way you would a library from Connections to business applications.

Implement an interface

To build a thunk that provides an interface, click New at the top of the home page's left menu, choose MCP server, and upload the interface file on the Tools step. That step lists each of the interface's tools with a type beside it — AI, Code, Database, Document Template, Spreadsheet Lookup, or AI Classifier — and View signatures shows each tool's inputs and output as property types. New tools start as AI tools. You can change the type; you cannot change the name or inputs. Those come from the file, because that is what other thunks bind to. Each tool also starts with the file's description, which you can refine later.

Thunk creates one custom tool per contract entry. The bodies are still yours to write. Creating the server this way does not publish it. When the implementations are ready, turn the export on under Admin → Deploy → Export.

The server remembers the interface it implements. The tools that come from the interface keep their names and inputs. Neither planning nor an edit in the tool builder can change them. Their descriptions can change, for example when planning adds an example input. When planning finishes, any interface tool whose inputs changed, or that went missing, is put back the way the file declares it. Planning can still add helper tools, which are smaller tools the interface tools call to do their work. Helpers aren't published by default, so the server offers exactly the interface. To publish a helper as well, switch it on under Admin → Deploy → Export.

An interface tool's object inputs can still grow, the way a provider's objects can. A field the interface declares can't be removed, renamed, or given a different type, but an object input can gain fields of its own. It can also use one of this thunk's Structure Types in place of a JSON Object, as long as the type has every field the interface's object lists. For example, if the interface's save_contact tool takes a contact object with name and email, the tool can take this thunk's Contact type with name, email, and company instead.

Once an interface tool uses a Structure Type, the Type Library protects it. You can add a field to that type. Removing, renaming, or retyping any of its fields is refused, even a field the interface doesn't list, and so is deleting the type. The message names the interface tool. To make that change, change the interface first, or switch the tool to a different type.

You can also match a single new tool to one entry of an interface. On + Add New Tool, point at a file you upload or at an interface one of this thunk's plug-in connections already uses, then pick the tool it should match. Thunk fills in that tool's name, description, and inputs, shows the inputs as property types, and leaves you to describe what it should do. The name and inputs then stay fixed while the tool builder writes the implementation. The description is yours to refine.

Coding agents

A coding agent building through the Builder API can do the same three things. The interface is always an inline JSON object — never a file upload. Where an agent writes an interface (creating a thunk or adding a connection), each tool can give its inputs and output either as JSON Schema (inputSchema, outputSchema) or as property types (inputProperties, outputProperties), with the same fields as a property add: name, description, type, and constraints. Thunk stores and returns the interface as JSON Schema in property-type form, so what an agent reads it can send back.

  • Export. Turn the publish switch on and choose tools. The design section export includes the interface document for the tools that are switched on, plus mcpUrl.

  • Require. Add a connection with kind: "plugIn" to declare a plug-in connection (alias + interface). Pass bindTo to bind or rebind it to an environment connection that matches; enabled: false removes the declaration from this thunk. Passing a new interface for an existing alias is refused if the current binding does not match it — pass bindTo in the same call to rebind, or bindTo: "" to unbind. The design section plugIns lists what this thunk requires.

  • Binding cases. bindingCases on the connection replaces the plug-in's keyed bindings ([] clears them; omit leaves them). A step's toolConfig set_binding_column names the work-item column that selects the case when that step runs. A custom tool's bindingCases names the input that selects the case on an AI or code tool.

  • Connection references. Add a Reference (REF) that mirrors a connection tool position — pass constraints.connectionTarget with the plug-in name or connection, the tool's name (toolName), and the path. The design summarizes how many positions each connection has in connectionRefPositionCounts; pass refPositions ("all", or a single connection, optionally with a toolName) to get the positions themselves in connectionRefPositions. Scope it to one connection when it has many tools.

  • Implement. Create a thunk with kind: "mcpServer" and an interface object to scaffold one custom tool per contract entry and remember the interface. Those tools cannot be deleted, and other tools you add are helpers that stay unpublished until the export includes them. Creating the server does not publish it — publish the export when the bodies are ready. Pin a tool, new or existing, to one interface entry with signature; pinning copies the entry's name, description, inputs and output onto the tool, and later updates refuse changes to that tool's name or input schema, and accept a reworded description. To move a provider to a new version of its interface, pin each tool again with the new version, then republish.

  • Check. Pass matchInterface when you read the design to see whether this thunk's published tools still satisfy a contract. Extra tools on this thunk are allowed, and descriptions are not compared; a missing required tool, or one whose inputs or output changed, is a mismatch.

Did this answer your question?