Manifest Executor
The "Manifest Executor" is part one of a three part feature,
- Manifest Executor (this document)
- Manifest (the rules & instructions)
- [Manifest Generator] (the ability for Linnet to generate a manifest)
The Manifest Exceutor is a function that will inject predetermined messages, components and/or Actions into an exisitng or new conversation or flow, determined by the [Manifest]. The Executor is responsable for checking the app conditions, (e.g. user intent, first time user, auth staus, permissions, etc) the goal is to ensure the [Manifest] can work and is allowed to work.
Task Chat Branch APIThese details are only updated with each release, for more acurate updates and keeping track of progress, see the task in GitHub.
- Overview
- Research
- User Details
- Development
Team
| Owner | Lead |
|---|---|
| Mendy | Sergey |
Status
| Doc Status | Product Status | Last Update | Version | Release | Phase |
|---|---|---|---|---|---|
| In Progress | Up Next | 04.03.2024 | 0.01 | Internal | Alpha |
Description
The Manifestd Executor is not a Manifest itself, it does not hold any pre-deternined asumtions, rules or directipons — it is simply responsible for ensuring a Manifest can be executed and for executing the Manifest's wishes, think of it as the foundation to the Manifest.
Linnet will be the one to determin whthere a manifest is used as a Guide or a Flow, the user should be able to switch between theses modes.
Reminders
Links & Resources
Research
the research listed here is spesifict to the Chat feature, for research related to the general Colibri development see the Research document.
Technical
Question - Can we support more Manifest types?
Question - Should we allow Colibri to generate its own manifest? Answer - Yes, this makes it a lot easier for devs (internal and external) to generate Guides, Stacks and Flows, it also allows us to launch Flows like "Vibe", "Page", "Canvas" and other products that hevely rely on generation.
Question - would it make things more simple for devs if they can create a Manifest using flutter and how do we support such capability?
Question - How do we ensure that Manifest that are published are not broken or reference an unavalible action or component? Answer - Build a linter, make sure all referenced actions or components are uploaded and redy to be published togethere with the Manifest.
Conclusion - How do we get data from arenas to form the arena layout and map the devices?
Sources
- [test]
Business
User Stories
Persona One
Update Coming Soon
As a developer I do not want to build out the onboarding for my flow, a simple document with the data I need should generate the onboarding for me
Flows
Personas
Development
All details related to how to build or had been built, how to use, etc are here.
- Features
- Phases
- Data
- Implementation
- Endpoint
Dependents
Below is a list of features that will be utilized in order to deliver the Manifest Executor and it's functionalities.
The details bellow are not comprehensive feature details but rather, describe how the features will be utilized within the account, for further details, please see the individual feature documentation.
-
Actions
Create an api to allow apps to add thier own actions in the place of the voice and live actions
-
Components
Dependent
These are the feature who repply on the Manifest Executor and thier dependents
The details bellow are not comprehensive feature details but rather, describe how the features will utilize the Manifest Executor, for further details, please see the individual feature documentation.
Phases
Phase One
- Build the Manifestd Conversations Feature
- Build the three esencal guids Auth, Preferences
phase Two
On the document we want to keep all the important data, the first fetch and fast to access, all secondary data should be stored on a subcollection and fetch sepratly (if this is cost sfective)
User Accounts should be a top level collection, each account will generate a new document within the "Accounts" collection.
Messages
- Message
- - Message 1
- - - type (offer a fea default options that the client can configure as well as custome options or offer numbered types and allow te client to give each type a title, this will enable the client to offer difrent feature or access levels based on account types)
- - - email
- - - number
- - - legal name (if connected wit a / our identity API this will allow for name/identity varification, useful for saftly and fintech and fraud protection)
- - - age (also opcinaly connect with identity api for varification)
- - - dob (also opcinaly connect with identity api for varification)
- - - varified (true, false)
- - - created (date)
- - - timezone
- - - langages
- - - contact detail
Intelegence
- names
- - name 1
- - - type (legal, nicname, madename, etc)
- - - name
- - - laguadge
- - - created (date)
- - - varified (true, false)
- - - varified source (api id)
Identification
- id
- - id 1
- - - type (licence, passport, health card, etc)
- - - issuer (US gov)
- - - id number
- - - status: verified
- - - issued (date)
- - - experation (date)
- - - Verify provider: (api id)
- - - Verify date: log id
- - - image
- - - id_proof`
Condissions
- Sessions
- - Section #1
- - - auth type (OTP, Google, Apple, Normal)
- - - device_type (Android, IOS, Web)
- - - device_token
- - - location
- - - activated (date)
- - - status (active, inactive)
- - - inactive (date)
Knowladge
Envierment
- location
- mood
- tone
Preferences
- prefrences
- - communication
- - - method (push, email, text)
- - - default (true, false)
- - - allow (true, false)
- - - block (true, false)
- - - level (all, update, security, system)
- - - channels (id, id, id)
- - privacy
- - - allow (true, false)
- - - block (true, false)
- - - allow user data collection (true, false)
- - - allow user data share (true, false)
- - - allow user data anonymize (true, false)
- - - allow user data deletion (true, false)
Implementation (Current State)
This section documents how the Manifest_executor feature is actually implemented today in colibri_api (backend), plus the client contract Flutter (colibri) must implement.
Backend — lib/features/Manifest_executor/
Clean-architecture layout:
Manifest_executor/
domain/
entities/ ManifestDefinition, ManifestStep, ManifestSession, ManifestEvent,
StepInstruction, ManifestIntentMatch, ManifestRuntimeResult, enums
repositories/ ManifestRegistry (catalog), ManifestSessionRepository (persistence)
services/ ManifestEngine, ManifestConditionEvaluator, ManifestIntentClassifier
usecases/ ResolveManifest, AdvanceManifest
data/
datasources/ ManifestYamlLoader (parses manifest/*.yaml), ManifestSessionFirestoreDatasource
repositories/ InMemoryManifestRegistry, ManifestSessionRepositoryImpl
services/ GeminiManifestIntentClassifier (LLM fallback for free-text intent)
presentation/
controllers/ ManifestController (Flutter-facing endpoints)
Manifest documents are static YAML files in [manifest/] (auth_Manifest.yaml, intro_Manifest.yaml, preference_manifest.yaml), loaded once at startup by ManifestYamlLoader and cached in InMemoryManifestRegistry. Adding or editing a Manifest usually requires only a YAML change and does not require changes to the Manifest Executor code — provided the Manifest only reuses step types, target components and action keys the Flutter client already supports; a new target (e.g. NewPaymentCard) still needs a matching Flutter widget before it can render. Because the YAML files are bundled with the backend, the service must currently be redeployed or restarted for the changes to take effect. See the Manifest document for the full YAML field/step-type reference and an authoring example.
ManifestEngine is the pure decision core (no I/O):
selectManifest— picks the firstcondition-triggered Manifest whose expression holds against runtimefacts(or resolves an explicit name), gated bycanRun(auth requirement + condition).selectManifestByIntent— deterministic keyword match: a chat message matches a Manifest if it contains one of itsintents, or (forstart: anywheremanifest) an edit verb ("change", "update", "изменить"...) plus one of the Manifest's stepkeys (e.g. "change my address" →preference_manifestat theaddressstep).ManifestConditionEvaluator— tiny boolean grammar forcondition:(fact == true,!=,&&,||; unknown facts are falsy).startSession— creates aManifestSession, generating a newconversationIdwhensession_isolation: new_conversation, and resolving the starting step index (viastartStepKey/indexOfStepKeywhenstart: anywhere).instructionFor— converts the session's current step into aStepInstruction(the only thing sent to the client — never the whole Manifest document).advance— applies aManifestEventto a session:abandoncloses it; anything else moves to the next step (or, forsteps_mode: dynamic, to whatevernextStepIndex/stepIndexthe brain put in the event payload); stepping past the last step marks the sessioncompleted. Eventpayloadis merged intosession.dataas accumulated progress/answers.
ResolveManifest (POST /manifest/resolve) decides which Manifest runs and returns its first (or resumed) step:
- Explicit
ManifestNamewins if provided. - Else keyword intent matching against
message. - Else
GeminiManifestIntentClassifier(LLM) as a fallback for free-form phrasing, returning a Manifest name + optionalstartStepKey. - Else the first matching
conditionManifest (e.g.intro_Manifestfor first-time guests).
It also decides whether to resume a prior active + save_and_resume session (continuing where the user left off), restart at the hub/overview step when the user re-invokes the Manifest generically without naming a specific card, or skip re-running an already completed Manifest (unless it's intent-triggered, which can always be re-entered, e.g. "change my address" after preference_manifest finished).
AdvanceManifest (POST /manifest/{sessionId}/events) loads the session, looks up its Manifest, applies the ManifestEvent, persists, and returns the next StepInstruction.
Sessions are persisted to Firestore via ManifestSessionRepositoryImpl / ManifestSessionFirestoreDatasource.
API surface (Flutter-facing)
| Endpoint | Method | Purpose |
|---|---|---|
/manifest | GET | Catalog of all manifest, each annotated with available (auth + condition check) so the client can grey out inapplicable manifest. |
/manifest/resolve | POST | Body: { ManifestName?, conversationId?, message?, startStepKey?, startStepIndex?, facts? }. Returns { session, step } or { manifest: null }. Called on app start and whenever the chat brain detects Manifest-worthy intent. |
/manifest/{sessionId}/events | POST | Body: { type, payload } where type ∈ step_completed | component_result | cta | auth_success | abandon. Returns { session, step } for the next step. |
facts passed to condition evaluation always include is_guest, is_logged_in, is_first_time_guest (derived server-side from the auth token) merged with any client-supplied facts.
StepInstruction (the payload Flutter renders) is intentionally minimal — only the current step, never the full Manifest:
{
"sessionId": "gs_...",
"ManifestName": "preference_manifest",
"stepIndex": 2,
"type": "component",
"target": "PreferenceAddressCard",
"isLast": false,
"done": false
}
Frontend — Flutter (colibri app)
The Flutter client is a separate project/workspace not present here, so its implementation could not be inspected directly for this update — the contract below is inferred from the backend API and should be verified/expanded against the actual Flutter source:
- On app start (and after login), call
POST /manifest/resolveand render whateverstepcomes back (or nothing, ifManifest: null). - Maintain a registry mapping
StepInstruction.target→ Flutter widget for everycomponent-type step (IntroCard,AuthCard,AccountPreferencesCard,PreferenceLastNameCard,PreferenceAddressCard,PreferenceDateOfBirthCard,PreferenceCitizenshipCard,PreferenceTaxDetailsCard,PreferenceExpiresCard, ...). - After a step is shown/completed,
POST /manifest/{sessionId}/eventswith the matchingManifestEventType(step_completedfor text/auto-advance steps,component_resultwith the captured field(s) inpayload,ctafor button taps,auth_successonceAuthCardcompletes,abandonif the user dismisses the Manifest) and render the returned nextstep. - For
steps_mode: dynamicmanifest (e.g.preference_manifest), the client (or the brain acting through it) may passnextStepIndex/stepIndexin the event payload to jump non-sequentially. - Chat-detected intents (free text like "change my address") should be forwarded as
messageto/manifest/resolverather than requiring an explicitManifestName.