Knowledge Base document trigger
Start one run each time a document finishes indexing in a knowledge base.
Add a KB Indexed trigger (trigger_knowledge_document) and Elizon starts the workflow each time a document finishes indexing in the knowledge base you choose — once per document, with no external system to call a webhook and nothing to poll.
This is the trigger for "do something to every new document": extract a contract's dates on upload, summarise a manual into a Data Table, flag a policy that mentions a term you care about.
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
knowledgeBaseId | string | '' | The knowledge base to watch, from this workflow's project. See Choosing the knowledge base. |
knowledgeBaseName | string | '' | Its name, kept for display so the node still says what it watched if the knowledge base is later deleted. |
event | indexed | indexed | The one event today: a document has finished indexing. |
It fires on indexed, not on uploaded
Deliberately, and it is the whole point of the trigger. A run started the moment a file is uploaded cannot search the file that started it — the text has not been chunked and the vectors have not been written — so an Agent pointed at it would reliably find nothing. By the time this trigger fires, the document is fully searchable.
The gap between the two is however long the indexing queue was: {{ trigger.upload_date }} is the upload time, not the indexing time.
Choosing the knowledge base
The picker lists the knowledge bases of this workflow's project, and only those. That is not merely where the picker looks — the project is the scope a fire is matched against, so a knowledge base from another project would save, publish, and then never fire. A workflow that belongs to no project has no knowledge bases to choose from at all, because knowledge bases are always project-scoped.
If a configured knowledge base is missing from the list it is kept rather than cleared, and labelled (not in this project) — it was deleted, or moved to another project. If the list itself could not be loaded the label is withheld, because a read that failed knows nothing about where your knowledge base is; you get the error instead. Nothing is guessed on your behalf.
Output
The payload is flat, like the email path and unlike the webhook and form paths, and its field names are the knowledge base's own — so the word you read out of the trigger is the word you write into an Agent's metadata filter:
| Expression | Value |
|---|---|
{{ trigger.document_name }} | The document's filename, exactly as the knowledge base stores it. |
{{ trigger.document_id }} | Its id in the knowledge base. |
{{ trigger.kb_id }} | The knowledge base it landed in — always the one the trigger names. |
{{ trigger.uploader }} | The user id of whoever uploaded it, or empty. See below. |
{{ trigger.upload_date }} | When it was uploaded, ISO-8601, or empty. |
{{ trigger.event }} | indexed. |
`uploader` can be empty, permanently
Empty is a real answer rather than a gap waiting to be filled, and there are three ways to reach it: a document uploaded before Elizon recorded uploaders, a document created by a path with no person behind it (a Package install's knowledge base import, a website crawl), and a user whose account has since been deleted. A workflow that must know who uploaded something has to handle the empty case.
It is an id, not an email address — Elizon keeps people's addresses in one place, so a workflow that needs a name or an address looks the id up rather than reading it out of the payload.
The contract-monitor pattern
The reason the payload leads with document_name. Put an Agent after the trigger and restrict its search to the one document that started the run:
- KB Indexed trigger, watching your
Contractsknowledge base. - An AI Agent with that same knowledge base bound, Metadata filters turned on in its Knowledge section, and instructions that tell it to search with
{"document_name": "{{ trigger.document_name }}"}. - A Data Table node writing the fields it extracted — renewal date, notice period, counterparty — one row per contract.
- Optionally a Recurrence-triggered second workflow that reads that table and emails you what expires in 30 days.
Without the filter, step 2 searches the whole knowledge base and the Agent happily answers about last year's contract. document_name is written on every chunk of every document in every knowledge base — it is not one of the optional metadata fields — so the filter works without configuring anything on the knowledge base itself.
Exactly once, and what a re-index does
Each document starts exactly one run per trigger. The run's identity is derived from the document's own id, which the workflow engine refuses to start twice. So:
- a crash between starting the run and recording progress does not produce a second run;
- re-indexing the knowledge base does not fire the trigger — neither a full rebuild after an embedding-model change, nor a re-chunk of one document, nor Elizon's own recovery of a document that was interrupted mid-indexing. None of them is a new document, and a trigger that fired on all of them would re-process your whole library every time you changed a setting;
- a replayed notification (a retried indexing step) is refused the same way.
Uploading many documents at once
N documents start N runs — one per document, as each one finishes indexing. There is no burst beyond that: the runs appear only as fast as Elizon can embed the documents, and they are subject to your plan's concurrency ceiling like every other run.
At the ceiling, a document's run is skipped rather than queued
Unlike the email path — which re-reads the folder on its next check and so simply defers the overflow — this trigger has nothing to come back to. If your organization is already at its concurrent-run limit when a document finishes indexing, that document starts no run, and nothing retries it later. It is recorded rather than silent: the run appears in the workflow's Activity tab as Concurrency limit reached, naming the document and the limit that refused it, so you can re-upload it or raise the limit. The trigger itself also shows the refusal while it lasts.
For a large import, upload in batches rather than all at once, or give the workflow something cheap to do and let it finish quickly.
Example
The first two steps of the contract monitor above:
name: Contract monitor
description: Extracts renewal terms from every new contract.
graph:
nodes:
- id: new-contract
type: trigger_knowledge_document
position: { x: 0, y: 0 }
data:
knowledgeBase: knowledgeBases.contracts
knowledgeBaseName: Contracts
event: indexed
- id: extract-terms
type: ai_agent
position: { x: 280, y: 0 }
data:
mode: existing
agent: agents.contract-reader
agentName: Contract reader
inputMappings: []
edges:
- { id: contract-to-extract, source: new-contract, target: extract-terms }In a Package
A Package can declare type: knowledge-document in its triggers, and it declares the knowledge capability. Unlike every other trigger in a Package, the knowledge base reference travels — it is written on the trigger node of the packaged workflow and resolved to the knowledge base the Package itself declares and installs.
That is the difference between a knowledge base and a mailbox or an FTP server: a mailbox belongs to whoever installs the Package, so carrying one would point the trigger at the wrong account; a knowledge base is an object the Package brings with it, so not carrying the reference would ship an entry point that can never fire. A trigger with no knowledge base chosen is refused at build time, naming the node.
compatibility:
requiredCapabilities: [knowledge]
triggers:
- id: new-contract
type: knowledge-documentOn the node:
- Travels:
knowledgeBaseName,event - Converted:
knowledgeBaseId→knowledgeBase(aknowledgeBases.<name>reference) - Never carried: none