Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.ntropii.com/llms.txt

Use this file to discover all available pages before exploring further.

Ingest sits between unstructured input (bytes, CSV uploads) and typed subledger rows. Runbooks use ntro.ingest for shared outcome contracts and tenant Postgres writes into the ingest schema — see also Subledgers for ledgers.* and Workflows overview for orchestration.

Package layout

ModuleRole
ntro.ingest.IngestOutcomeStructured summary of one ingest attempt: parsed/accepted/rejected counts, status, message, optional reasons and progress.
IngestIssueSummary / IngestProgressSnapshotSupporting types for reject reasons and progress gates.
insert_submitted_recordPersists structured rows to ingest.submitted_records (data-ingest / agent submissions).
insert_extracted_recordPersists reviewed AI extraction to ingest.extracted_payloads.
IngestOutcome is re-exported from ntro.workflow next to NtroWorkflow so workflow code can depend on a single import surface.

User feedback from workflows

NtroWorkflow.set_user_feedback(kind=..., payload=...) attaches a workflow-agnostic envelope to the current pending action:
  • Top-level feedback on the pending action
  • display_hint.config.feedback for Tenant UI components (e.g. FILE_UPLOAD reads kind: "ingest" and shows counts / message)
While a signal gate is open (e.g. waiting for more accepted rows), await_signal_with_action merges the latest stored feedback into the merged action so operators keep seeing progress.

Example: attach ingest feedback

from ntro.ingest import IngestOutcome
from ntro.workflow import NtroWorkflow

class MyWorkflow(NtroWorkflow):
    async def _step_collect(self, ctx) -> dict:
        outcome = IngestOutcome(
            parsed_rows=100,
            accepted_rows=0,
            rejected_rows=100,
            status="empty",
            message="No rows matched required columns after parse.",
        )
        self.set_user_feedback(kind="ingest", payload=outcome)
        await self.await_signal_with_action(
            predicate=lambda: self._have_enough_rows(),
            action={"kind": "submit_file", "reason": "Upload expense CSV."},
            display_hint={
                "component": "FILE_UPLOAD",
                "config": {"title": "Upload expenses"},
            },
        )

Data lifecycle (reference)

  1. Unstructured — raw files / bytes (ingest.submitted_documents).
  2. Loosely structuredntro.ingest outcomes + ingest.submitted_records / events.
  3. Structured + typedntro.subledger / ledgers.*.
  4. External GL shapentro.capabilities.gl posting contracts when applicable.

Workflows overview

NtroWorkflow, @ui_step, and pending-action wiring.

Subledgers

Domain rows after ingest.