Python API
Core orchestration, stores, retrieval, workflow formats/scaffolding/preview, and Dify/n8n conversion entry points.
This page highlights stable composition surfaces. Run make docs in a source checkout for the
symbol-level pdoc site.
Agent orchestration
from collections.abc import Sequence
from datetime import date
def answer_question(
question: str,
store: FactStore,
provider: LLMProvider,
*,
reference_date: date | None = None,
narrative_retriever: NarrativeRetriever | None = None,
intent_parser: IntentParser | None = None,
decomposer: QueryDecomposer | None = None,
history: Sequence[HistoryTurn] | None = None,
) -> AgentResult: ...HistoryTurn is tuple[str, str]. Only assistant is recognized as the assistant role; other
roles normalize to user. History is inserted between the system message and current question for
generation only. It is never sent into intent parsing, security decisions, retrieval queries, or
evidence/citation assembly.
AgentResult exposes answer, answer_plain, route, optional clarification, tool_results,
and sources. answer_plain omits the inline citation suffix for UIs that render sources
separately.
from ragspine.agent.agent import answer_question
from ragspine.agent.llm_provider import MockProvider
from ragspine.storage.fact_store import SqliteFactStore
store = SqliteFactStore("data/fact_metric.db")
store.init_schema()
result = answer_question("China FY2024 revenue", store, MockProvider())FactStore is a runtime-checkable Protocol; instantiate SqliteFactStore, not the Protocol.
Fact.metric(...) is the keyword-only helper for constructing facts without transposing the frozen
identity fields. Every stored fact retains source_doc_id and source_locator.
Narrative storage and retrieval
Narrative Chunk/StoredChunk records include additive parent_id, heading, window_text, and
parent_locator fields. Existing SQLite databases migrate additively. Parent-child and sentence-
window expansion happen at the store/retrieval layer: the child hit keeps its own text, chunk ID,
and locator for citation while window_text can become separate generation-only prompt_text.
A restricted child is dropped before expansion and cannot leak through a parent/window.
Retrieval supports metadata-filter operators eq, ne, in, nin, gt, gte, lt, lte,
and between. Filters are narrowing and preserve result order. MultiIndexRetriever queries each
selected library independently, fuses rankings with RRF, and attaches library_id provenance; a
router failure searches all configured libraries. Economy mode constructs neither an embedding
backend nor a vector store.
Workflow documents
from ragspine.workflows.formats import (
dump_dify_yaml,
dump_json,
load_workflow,
parse_workflow,
)
workflow = load_workflow("workflow.toml")
same_shape = parse_workflow('{"app":{"mode":"workflow"}}', format="json")
json_text = dump_json(workflow)
yaml_text = dump_dify_yaml(workflow)All accepted JSON/YAML/TOML inputs normalize to a JSON-compatible mapping. TOML text needs the
explicit format unless loaded from a .toml path. The format parser rejects duplicate keys,
non-finite numbers, unsafe YAML, and oversized or deeply nested documents. The file loader also
refuses links and non-regular files.
Catalog and scaffolding
from ragspine.workflows import scaffold_workflow
result = scaffold_workflow(
"invoice extraction and approval",
template_id=None,
reuse=True,
)
print(result.workflow)
print(result.yaml)Scaffolding is pure with respect to the filesystem: it returns configuration and never writes or
executes it. Catalog APIs list/get defensive copies. An explicit template returns confidence 1;
otherwise matching uses configured score/margin thresholds and falls back to fixed generation.
The CLI additionally handles safe atomic/exclusive file creation.
Preview v1
The workflow preview builder returns a display-only JSON-compatible object with
preview_schema_version: 1, nodes, and edges. It contains geometry and labels, not prompts,
variables, credentials, provider configuration, or executable code. Validate the version before
rendering; do not feed preview JSON back into an executor.
Dify and n8n
ragspine.dify parses Dify YAML into an intermediate representation, analyzes it, and generates
imperative Python for the ragspine or spineagent target. Code generation is not execution.
ragspine.n8n.n8n_to_dify and ragspine.n8n.dify_to_n8n perform pure conversion and return the
target mapping plus warnings. Unsupported semantics are reported rather than silently claimed as
equivalent. Original n8n metadata is retained for round trips where possible.
App factory
from ragspine.service.api.app import create_app
app = create_app(
config,
provider=provider,
queue=queue,
faq_cache=faq_cache,
workflow_matcher=workflow_matcher,
)The service package is optional. Its workflow execution surface is disabled by default and cannot accept a client-supplied provider expression.