Skip to main content

Schematized State

The state that is maintained during the execution of each AI workflow instance

Each workflow instance maintains state to capture the progress of the work between steps. The input and output state data for every step is schematized – it has an expected structure.

If you are familiar with database applications, you might think of each workflow request being associated with a "structured database row" that gradually gets filled in as the workflow process is executed. For example, an expense report approval workflow might have structured state like this:

  • Input: EmployeeName, ExpenseDate, ExpenseReceipt

  • Step 1 (“Get Details”): ExpenseTotal, LineItems, Taxes

  • Step 2 (“Categorization”): ExpenseCategory

  • Step 3 (“Approval/Rejection”): ApprovalDecision

Each workflow instance is represented by a “row” with 8 properties (EmployeeName, ExpenseDate, ExpenseReceipt, ExpenseTotal, LineItems, Taxes, ExpenseCategory, ApprovalDecision)

When you open Work Items in the Run section of the left pane, you will see a familiar tabular view of all the work items (workflow instances). The AI Task column is the current step's live chip — Working, Waiting, Waiting for tool, and the rest — not the work item's Status. See What Working, Waiting, and Waiting for tool mean. If you move the mouse over a column header, you will see a column menu (“three vertical dots”). Choose Column properties to see and change the definition of that state property, Add column to add a new property, or Delete column to remove one. Built-in columns such as Name and Status cannot be deleted. To filter, add, download, or act on work items from this list, see How to work with your work items list.

Once you have filtered this tabular view down to the rows you care about, you can save that view as a named report and reopen or share it later. See How to save a report from your work items.

The “schema” or structure of each of these properties is important because it provides important control information to the AI agent. “ExpenseReceipt” is not just any arbitrary data. You may know it will be a link to a file. You might know that you expect it to be a PDF file. You might know that it contains receipts for expenses in USD. Now, when your AI agent needs to look at and understand a receipt in Step 1, it can do a better job because it knows to expect a PDF file with expenses in a particular currency.

Likewise, the ExpenseCategory may not be arbitrary. Your company may have six specific categories and listing those makes the structure much more specific. Now when your AI agent needs to categorize the expense in Step 2, it will only choose from one of the enumerated categories.

More schematization leads to greater AI reliability

Schematization Elements

Every state property has these different elements of schematization:

  • Name: always pick a semantically meaningful name for the property. Obscure “internal” names (eg: “Property_123”) cannot be interpreted by the AI agents. On the other hand, a name that appropriately captures what it is supposed to represent (eg: “EmployeeName”) helps steer the work of the AI agent.

  • Description: The property description is also very important as it is a longer and more detailed way to describe the data that will be persisted in an instance of this property. The description can serve to specialize input properties (eg: “This is a PDF file of 3 or less pages, representing an invoice from one of our Malaysian customers”). It can also serve to constrain the work of the AI agent when it computes and persists output properties (eg: “This property holds the email address of our team sales rep for this customer”).

  • Type: Just as in a database or project system, each property can have a type (Number, Text, File, Image, etc.). Thunk.AI supports a growing number of property types. By choosing the most appropriate type, the thunk designer steers the AI agents with additional information, controls the updates of the AI agents to fit the type, and influences the UI presentation of data based on the type. A special kind of type is a List type. If a property is specified to be a List of Text, then the state maintained can be more complex with a nested list maintained for this property. When several properties or tools share the same object shape, you can define that shape once as a Structure Type and reuse it everywhere; see Structure Types and the Type Library.

  • Type Constraints: based on the choice of the type, further type constraints can be specified. For example, a Number can be constrained with min and max values. It is very common for Text to be constrained with a fixed enumeration of allowed values.

  • Required: There are two Required settings, and they do different things.

    • Required on the property itself applies when a work item is created. A request that arrives by email, through a webhook, or from the shared form becomes a work item only when every Required input has a value. It does not make a workflow step fill the property in. Most workflows have at least one input they cannot start without, so mark those inputs Required.

    • Required to start and Required to finish apply to one step. In a step's AI Instructions, each property under Input properties can be marked Required to start, and each property under Output properties can be marked Required to finish. When a Required to start input is empty, the step does not run; it waits for a person. When the AI agent finishes its work with a Required to finish output still empty, the step does not finish; it waits for a person, with a note naming the missing property. A Yes/No output set to No counts as filled in; one left unset does not.

Choosing which inputs are required

Look at each input of the workflow and ask whether the work can begin without it. The document to process, the request to answer, or the person who asked usually cannot be missing, so mark them Required. Leave an input optional only when the workflow has a sensible thing to do without it, such as a note from the requester or a reference number that is not always known.

When a request arrives by email, through a webhook, or from the shared form, the AI agent that turns it into a work item has to fill in every Required input. If one is missing, no work item is created. If every input is optional, an incomplete request becomes a work item anyway, and the problem shows up steps later as a confusing result instead of at the start.

When you write tests for the workflow, include a case that leaves out a required input. See Test plan design.

Choosing which outputs are required

For each step, look at its output properties and ask whether the work that follows can go on without each one. A decision the next step acts on, a value a report or a person relies on, or a Yes/No that routes the work item usually cannot be missing, so mark it Required to finish on that step. Marking the property itself Required does not do this: that setting is checked only when a work item is created.

Required to finish always applies. When a value is needed only in some cases, such as a filing deadline that exists only for an escalated case, leave it optional and use a Step Finish Condition instead. See Run a step only when a condition matches.

Choosing a property type

Choose the most specific type that fits what the property's description says it holds. Use Calendar Date for a date where the time of day does not matter, such as a deadline or a birthday, and Date Time when it does. Use URL for a link to a web page, File for a document, Image for a photo or screenshot, Address for a street or postal address, Location for map coordinates, and Country when the value is specifically a country. Use a Reference when the property should always show the same value as another property you already have — pick that other property as the target, and the two cannot drift. A Reference can also take its type from a position in a connected tool; see Reuse thunk interfaces and plug-in connections.

Text is the most permissive type, and it is the right choice whenever no more specific type fits. An email address or a phone number has no dedicated type, so Text is correct for it. Number is for quantities; an identifier that happens to contain digits, such as a ZIP code, is Text. Yes/No is for exactly two possible values.

Use a Conversation property for a two-way email or chat thread with someone outside the thunk. If the AI should send a message and wait for the reply, set Sending messages to Send messages, with the option to wait for a reply, and list the conversation under that step's Output properties. A Conversation that has never had this set does not wait. See Conversation properties.

When the description says the property holds several values — "a list of URLs", "the tags for this request" — make it a list of that type rather than a single value.

When the description says the property holds a value with several parts — a contact with a name and an email, an address, an invoice line item — make it a Structure Type: a named shape defined once and reused across columns, tools, and other types. Prefer this over a loose JSON object for any shape you know, and over several separate columns when the parts belong together. See Structure Types and the Type Library.

The description, not the name, says what the property holds, so make the two agree: a property described as "a link to the customer's dashboard" should be a URL, whatever it is called.

Values the AI agent copies

Some values have to be passed along exactly as they are: an order number, a customer id, a ticket key. The AI agent passes them by copying them into each tool call, and a copied value can come out changed, with a character dropped or two digits swapped. Make such a value hard to get wrong:

  • Give it its own property with the tightest constraint that fits. A fixed list of allowed values is best when there is one. Otherwise, give it a minimum and maximum length, so a value that lost or gained characters is rejected. An AI agent building through the FDA MCP can set these, and can also add a format pattern such as "# followed by seven digits". The agent is told about the pattern, but it is not enforced, so the tool that uses the value should still check its format.

  • Make every tool input that carries it a Reference to that property. The input then takes the property's type and constraints, so a value that breaks them is rejected before the tool runs. See Inputs in Custom Tools.

  • Keep such values short. Each tool that passes the value on to another tool is one more copy.

  • On a workflow step, map the field. Map I/O fills that tool input from the property, so the agent never types the value into the call. Use the same control to write a large tool result onto a step output without the agent copying it back. See Map a tool's inputs and outputs to the work item.

When you review a thunk, list the tool inputs that take an id as plain text; each should be a Reference to a constrained property. On a step that calls a tool with a large property, or that records a large tool result, look at the run's tool call and map those fields.

Did this answer your question?