a9script

Docs / Endpoints: webhooks, APIs, MCP, apps

Parameter structures

For an author whose script or configured call is reached by somebody else — another application, an assistant, a colleague’s integration — and who needs to say what it takes.

A parameter structure names the shape of a JSON value once, in your environment, and everything that needs to say a shape then says the name. It is the only thing on this platform that describes data rather than doing something with it.

It is optional. A script that declares nothing and a configured call whose parameters say nothing about their shape behave exactly as they always did. Declare one when somebody outside your environment has to get the shape right without asking you.

What a structure is

A list of fields. Each field has a name, a kind, whether it is required, and a description — and nothing else.

The five kinds are string, number, boolean, object and structure. Four of them are the JSON kinds you would expect. The fifth, structure, is how a shape holds another shape.

That is the whole vocabulary. There are no unions, no optional-unless, no minimum lengths, no patterns, no inheritance. This is deliberate, and it is why the model is small enough to hold in your head and small enough for a client to use: a structure is what you hand to something, not a type a language enforces.

Nesting is a NAME, never an inline shape

A field of kind structure names the structure it holds. You cannot write the inner shape inside the outer one — there is nowhere to put it.

So a purchase order with a customer inside it is two structures, not one:

Customer          fields: email (string, required), name (string)
PurchaseOrder     fields: reference (string, required),
                          customer (structure → Customer, required),
                          lines (structure → OrderLine, array)

This is the half authors get wrong, and the reason it is worth the friction: a shape that can only be referenced by name is a shape you can reuse, rename in one place, and see the users of. An inlined one is a copy nobody knows about.

Two consequences worth knowing before you start:

  • Order does not matter. A structure may name one that does not exist yet. Create them in whatever order suits you; a name that resolves to nothing is reported where it runs, not where you save it.
  • A cycle is refused when you Activate. If A holds a B that holds an A, the platform names the loop and refuses it, because every consumer walks a structure without a depth counter.

array of is a flag, not a kind

A field marks itself as a list with a flag beside its kind: an array of strings, an array of OrderLine. There is no array kind and no item type.

Which means an array of arrays cannot be written at all. That is not an oversight — it is the model refusing to grow a type system. If your value genuinely is a list of lists, the field’s kind is object and you have said so honestly.

object is the escape hatch

A field of kind object accepts any JSON object. Use it where the shape is somebody else’s and changes on their schedule, or where saying it would take more structures than the value is worth.

An object field is a promise that there is a value and it is an object. It is not a promise about what is inside.

Where a shape is checked

Three doors ask, and each asks at the moment where the answer is cheapest:

  • At an answering endpoint — after the caller’s credential and before any run starts. After the credential, so a stranger cannot read your shape out of a refusal; before the run, so a call that could never work costs you nothing.
  • At an endpoint an assistant calls — the same check on a tool call’s arguments, and the tool’s own input schema is generated from the structure, so a client is told the shape before it composes a call.
  • On a configured call’s Test — before the call leaves, so an author who passed the wrong shape is told that, rather than told what the far end thought of it.

And one door only reports. A webhook’s sender is not yours to hold to a shape, and nobody is on the connection to be refused, so a mismatch becomes one warning line in the run’s own log and the run happens anyway.

Where a shape is NEVER checked

A script’s own call. Inside the platform the language is JS, and a script calling a configured function is not checked against the structure that function declares:

const contact = FindContact({ email: input.event.body.customer });

log("looked up", { found: contact !== null });
return contact === null ? "no contact" : contact.id;

That call goes out whatever any structure says. The reason is the boundary a structure is for: it describes what crosses INTO your environment from somewhere you do not control. Your own script is already inside.

The second place is the corollary: a value your script builds is never checked either. If you assemble a body and hand it to a configured call, the platform checks the argument rules the function declares — a missing parameter, a value where the function expects one — and nothing about a structure.

Two things a check will never do

It never converts. A "5" where a number was declared is a refusal, not a five. Guessing what a caller meant is how a run writes the wrong thing into somebody else’s system with nothing anywhere saying so.

It never echoes what arrived. A refusal names the field and what was expected. What arrived may be a credential posted to the wrong door, and a message quoting it would put it into a log, a run record and a reply.

One more thing it deliberately does not do: an undeclared field passes. A structure describes what you hand to something, not a closed contract. Refusing an extra field would break your integration the day the far end adds one, on their schedule rather than yours.

In the editor

Declare a structure as a script’s input and the editor knows the body’s shape while you type: the fields complete, they hover with their descriptions, and none of it needs an Activate. A reference the editor cannot resolve becomes any rather than a guess — it will never invent a field for you.

Rendered from docs/guide/parameter-structures.md in the product's own repository, at build time. Found a problem on this page? Write to the address in the footer.