Elizon Docs
Features & SpecsPortable definitions

Portable definitions

The definition files that describe each object in a Package.

Each object the manifest lists has a definition file: YAML in your project, which build converts to canonical JSON inside the .pkg. A definition describes what the object is and how it behaves, with nothing that identifies an Organization:

  • other objects are referenced by manifest-local name (agents.intake, tools.calendar), never by id,
  • models, credentials, documents, speech providers and trunks are referenced by Slot id (llm.slot: reasoning, credentialSlot: calendar-access),
  • nothing is personal or secret.

build refuses a definition that would carry an Organization identifier (PORTABLE_ORG_IDENTIFIER_LEAK) or personal data such as an email address (PORTABLE_PERSONAL_DATA_LEAK).

Carried text

validate, and so build, scans every string in every definition file for two things, and refuses the Package when it finds either, with the exceptions below:

  • an email address, refused with PORTABLE_PERSONAL_DATA_LEAK. A Package travels by email, file share and USB, so a sticky note, prompt or description must not name a person. A {{ }} expression that resolves to an address at run time, such as {{ trigger.email }}, is not an address and passes. The check is loose: a file name like logo@2x.png matches it too, so rename anything that isn't an address.
  • a secret reference: a value that starts with vault:, or contains {{secret.…}}. It is refused with PORTABLE_ORG_IDENTIFIER_LEAK, or PORTABLE_DEFINITION_INVALID in a Tool file (see Tools). A reference points into the author's own vault, so it never travels. Use a credential Slot.

Every hit is reported. The path names the collection, the object and the field, such as agents.support.config.instructions or workflows.triage.graph.nodes[2].data.text, and the message names the definition file.

The scan covers the agents, teams, workflows, tools, skills, knowledgeBases and dataTables definitions and the voice and sip files. Three exceptions:

  • Machine content — a Tool's embedded OpenAPI spec, and a Workflow Code node's source (data.code, on a code node only). An address-shaped match there is a PORTABLE_MACHINE_CONTENT_EMAIL warning at the same path, such as tools.orders.spec.info.contact.email or workflows.triage.graph.nodes[3].data.code, and the Package still builds. A third-party spec's vendor contact, or Python like x@self.weights, may stay; a person's address must still go. A secret reference there is refused as anywhere else, and every other field of a Tool or Code node (an action description, a header value, a Code node's inputExpression) is scanned as usual.
  • A Workflow's people fields (a human-review assignedTo, a Send Email to, cc, bcc or replyTo) holding a literal address are stripped by build with a warning, not refused. A human-review fallbackAssignedTo is always stripped, whatever it holds. See People fields.
  • A Skill's files (the SKILL.md body, reference files and scripts) are the Skill's content, not definition fields, and are not scanned. Its frontmatter name, description and allowed-tools are.
ObjectManifest entryPage
Agentagents: [{ name, ref }]Agents
Teamteams: [{ name, ref }]Teams
Workflowworkflows: [{ name, ref }]Workflows
Tooltools: [{ name, ref }]Tools
Skillskills: [{ name, ref: ./skills/x/ }]Skills
Knowledge BaseknowledgeBases: [{ name, ref }]Knowledge Bases
Data TabledataTables: [{ name, ref }]Data Tables
Voice, SIPvoice: { ref }, sip: { ref }Voice and SIP

Where to start

The quickest way to get correct definition files is to start from one: every init starter and every demo Package contains valid, commented definitions. Edit from there, and run validate after each change: it checks every definition file against its schema and reports the exact path of anything wrong.

Keep definitions in step with the platform

Definitions mirror the settings the corresponding Studio editor offers. When a field's meaning isn't obvious, open the same object type in Studio and look at the equivalent setting.