AFI Factory is the strategy workshop for Agentic Financial Intelligence.
Factory helps traders, quants, builders, and agents turn market ideas into repeatable AFI-powered workflows — deciding what signals to watch, what analysis to run, how scoring should apply, and how the workflow connects into AFI. Factory prepares the playbook; it does not trade, and it does not score.
Where Factory sits in AFI:
- Factory builds the playbooks — the strategy and agent workflows.
- Machine scores the signals.
- Gateway provides protocol access.
- MCP connects agents.
- BUY SELL TERMINAL, if and when built, is the trader-facing cockpit.
You work with Factory through three surfaces, all backed by one authoring engine:
- a local CLI — for advanced users and operators to create, check, and prepare strategy workflows;
- an MCP interface — so an agent can help design, check, and prepare those workflows;
- a TypeScript library — to build on the same authoring functions directly.
Under the hood — Factory is the analyst-configurable pipeline authoring implementation (SLOT-FCP-FACTORY, authorized by
afi-governance/decisions/factory-configurable-pipelines-v1.md, D-FCP-4). The contract-level mechanics — pipeline manifests, canonical hashing, and the typed operation layer — are documented in the technical sections below and remain exact.
Factory is:
- a strategy-workflow authoring surface — define what a strategy watches, what analysis runs, and how scoring applies;
- a local CLI for preparing and checking AFI workflows;
- an agent-facing MCP surface for designing and validating workflows;
- a developer-accessible TypeScript library.
Factory is not:
- a trading terminal or trade-execution system;
- the scoring engine — that is Machine;
- the protocol gateway — that is Gateway;
- a hosted web app or visual editor;
- a wallet, rewards, or settlement surface.
Factory prepares the playbook; other AFI surfaces run it.
The afi-factory CLI is an authoring tool. It creates, checks, and prepares
AFI strategy workflows — it never places an order, connects to a broker, moves a
position, or runs a live strategy.
A trader-facing cockpit — BUY SELL TERMINAL or another future app — is a separate surface built for traders. A trader may act through such a terminal, a web app, or an agent, while Factory works behind the scenes to prepare the workflow those surfaces rely on.
Factory prepares the playbook; the terminal (when it exists) is where a trader acts on it.
- Template authoring + instantiation — author
afi.pipeline-template.v1documents with{"$param":"<name>"}value slots; instantiate them (defaults applied, values validated against each parameter's schema fragment, fail closed) into concreteafi.pipeline.v1manifests. - Manifest validation — strict AJV validation against the vendored,
byte-pinned afi-config contract closure (
src/governed-schema/, pinned to afi-configd6f2504805059ffa09d8c1bfcecb67cd47abcea2), plus the semantic graph layer the schemas delegate to tooling: unique node ids, known edge endpoints, Kahn acyclicity, exactly one non-bypassable scorer sink, join-declaration rules,prefer:parent checks, condition-path well-formedness, timeout/retry bounds, and — against a provided plugin-manifest set — category/plugin binding checks (unknown pluginId/version is an error, never a fallback),paramsSchemaconfig validation,multiInstance,permittedFailurePolicies,mayFeedScorer, and category-level ordering constraints. - Canonical hashing —
canonical-json-hashing.v1exactly per the governed spec, proven against all six vendored KAT vectors on every test run. - Graph inspection — execution order, parallel waves (Kahn levels), node
table, join/condition summaries; human text and
--json. - Plugin scaffolding —
afi.analysis-plugin.v1manifest skeletons plus a TypeScript implementation-contract stub.
Connect an agent to Factory so it can help design, check, and prepare AFI-powered strategy workflows. For example: a quant tells their agent "draft a momentum strategy that watches 15-minute candles, add a sentiment check, and score it with an AFI scoring template." The agent uses Factory's tools to draft and assemble the workflow, validate it against the available analysis steps, inspect the execution graph, and give it a verifiable workflow fingerprint — without a person hand-writing a manifest. Factory only authors and checks; the agent never trades or scores through it.
Under the hood, every authoring capability above is exposed to agents through
one implementation-backed operation registry (src/operations/). The
TypeScript library, the afi-factory CLI, the machine-readable capability
catalog, the generic agent-tool definitions, and the MCP interface are all
projections over the same typed operation handlers — a capability cannot
exist without a real handler, a validated input schema, a validated output
schema, a declared filesystem/security policy, and test coverage. Changing or
removing an operation changes every projection.
- Machine-readable capability discovery —
afi-factory capabilities --jsonemits a deterministic catalog (stable id-sorted order, no timestamps/paths/ usernames; equivalent registries hash identically via--hash). - Generic (framework-neutral) agent-tool definitions —
capabilities --toolsemits neutral{ name, description, inputSchema }tools suitable for any function-calling / tool-using agent system; no framework is the authority. - MCP-compatible stdio adapter —
afi-factory agent serve --transport stdio [--workspace <dir>]speaks newline-delimited JSON-RPC 2.0 (initialize,tools/list,tools/call). It opens no network listener, executes no shell, performs no dynamic import, and grants no filesystem access beyond a mutating operation's declared workspace boundary. - Pipeline-component discovery —
factory.plugins.listsurfaces each analysis-plugin's category, version, schema refs, determinism, params schema,multiInstance, andmayFeedScorer, plus the five analyst-configurable categories (technical,pattern,sentiment,news,aiMl). - Fail-closed filesystem boundary — every mutating operation
(
factory.plugin.scaffold,factory.artifact.package) writes ONLY inside an explicit workspace root; traversal, absolute-path escape, symlink escape, symlinked-parent escape, and unauthorized overwrite fail closed on canonical paths (never string prefixes).
The operation layer is implementation metadata for authoring AFI pipeline artifacts. It is not a network-wide capability catalog: mapping externally exposed capabilities across AFI services is reserved for the future API Atlas, which this repo neither implements nor claims.
- It is not a protocol authority: the canonical contracts live in afi-config; nothing Factory emits is canonical until validated against them.
- It is not the executor: no pipeline runs here (afi-reactor is the
governed runtime), no plugin code is loaded, no dynamic imports — manifests
bind plugins by
pluginId+pluginVersiononly; binding to code happens in the consuming runtime's build-time registry. - It does not persist evidence, touch lifecycle states, or talk to any store or network service.
- There is no visual editor and no execution of untrusted code: conditions are bounded declarative predicate trees (pure data), and templates parameterize values, never topology.
Two distinct acts, never conflated:
- Configuration (this repo's output): authoring a template, instantiating
a manifest, writing an
afi.analyst-strategy-config.v1. Selecting a UWR profile or decay template in a config confers nothing — no recognition, no qualification, no rewards. - Registration (D-FCP-5): an administrative, schema-validated, reviewed
registry update in afi-config (
afi.analyst-strategy-registration.v1, provider bindings). The runtime fails closed for unknown, unregistered, or inactive identities. Factory validates registration/binding documents but does not perform registration.
npm ci && npm run build
# validate the official manifest against the official plugin set
npx afi-factory pipeline validate \
official/froggy-trend-pullback/pipeline.manifest.json \
--plugins official/froggy-trend-pullback/plugins
# inspect the graph (waves, node table, joins)
npx afi-factory pipeline inspect \
official/froggy-trend-pullback/pipeline.manifest.json
# hash the official manifest (matches the canonical composition pin)
npx afi-factory hash official/froggy-trend-pullback/pipeline.manifest.json \
--kind pipeline --json
# cross-validate the analyst config against its pinned manifest
npx afi-factory analyst-config validate \
official/froggy-trend-pullback/analyst-config.json \
--pipeline official/froggy-trend-pullback/pipeline.manifest.json \
--plugins official/froggy-trend-pullback/plugins
# start a new pipeline project (scaffolds a value-parameterized template)
npx afi-factory init my-pipeline-projectEvery command exits nonzero on invalid input, emits --json machine output,
and reports errors with JSON-pointer paths. No command ever reports
valid: true without executing real validation.
Per D-FCP-6, pipeline identity is pipelineId + pipelineVersion + canonical
manifestHash. Hashing follows the governed
canonical-json-hashing.v1
spec: SHA-256 over the UTF-8 bytes of the canonically serialized JSON
(recursively key-sorted objects, authored-order arrays, no whitespace,
shortest ECMAScript number form) after removing the artifact's excluded
top-level fields (description/metadata for manifests, metadata for
analyst configs). Conformance is pinned by the six vendored KAT vectors
(src/governed-schema/canonical-json-hashing.kat.json).
Domain tags carried on the emitted CanonicalHash objects are the
D-FCP-7 registered composition tags: afi.d2.composition-manifest
(manifestHash), afi.d2.analyst-config (analystConfigHash), and
afi.d2.plugin-set (pluginSetHash) — exactly as listed in the vendored
spec's exclusion table
(canonical-json-hashing.v1.md §3,
W3a amendment). The domain tag is carried on the reference, never mixed
into the digest.
pluginSetHash composition rule — the canonical hash of
{
"schema": "afi.plugin-set.v1",
"plugins": [
{ "pluginId": "...", "pluginVersion": "...", "implementationVersion": "..." }
]
}with plugins sorted by pluginId (then pluginVersion for repeated ids,
plain string comparison) — order-insensitive by construction, and sensitive to
implementation upgrades via implementationVersion.
The committed hashes of the official artifacts live in
official/froggy-trend-pullback/hashes.json
and are recomputed + asserted by CI on every run — they equal the pins carried
by the canonical analyst-strategy registration and the runtime composition
provenance, and downstream waves pin them.
The D-FCP-8 posture, applied to authoring:
- missing/invalid input fails honestly — parse errors, schema errors, and graph violations are reported with JSON-pointer paths and a nonzero exit;
- instantiation fails closed — a missing required parameter, an ill-typed value, an unknown parameter, or a graph-inadmissible result is an error, never a silent default;
- hashing refuses invalid artifacts —
afi-factory hashvalidates first; - fail-soft is declared, never implied —
degraderequires explicitcritical:false, must be permitted by the plugin'spermittedFailurePolicies, and optional join parents are explicitoptional:trueedges (degradations are recorded by the runtime, never silent).
afi-factory pipeline inspect (and template inspect) derives, from the
declared dependency structure only:
- execution order — a deterministic topological order;
- parallel waves — Kahn levels (concurrency is derived, never assumed);
- node table — category, plugin binding, criticality/failure policy, timeouts/retries, config;
- join summary — policy, merge strategy, conflict rule, per-parent optional/conditional flags;
- condition summary — operators and paths per gated edge.
official/froggy-trend-pullback/ carries
byte-identical copies of the canonical afi-config registry records for the
current official composition on the five-lane provider runtime: the registered
pipeline manifest froggy-trend-pullback v1.3.0, the canonical
analyst-strategy config, the seven bound plugin manifests, and the committed
canonical hash pins (hashes.json).
The v1.3.0 graph: a technical entry fanning out to pattern (via the
candles port), sentiment, and news; the aiMl lane joining the four
sibling lane outputs; one deterministic five-category namespace-by-node
merge; and the single afi-scorer-froggy-trend-pullback sink. Every category
lane selects its provider through an explicit providerInstanceRef (the
all-five keyless/self-hosted reference profile; the aiMl lane pins the
Tiny Brains provider-instance record 1.1.0), and all five lanes are
required: the lanes are fail-fast under the governed default — a failed
lane yields no scored evaluation.
Because provider selection is authored at the manifest layer and templates parameterize values, never topology or provider selection, the official provider-backed composition is not template-produced: Factory vendors the canonical records directly and validates, hashes, inspects, and packages them.
The eight configurability proof graphs live under
fixtures/conformance/ — clearly non-production
fixtures exercised by the test suite.
- Quant: authoring a strategy workflow
- Plugin developer
- Provider binding
- Operator: installing and running validation
MIT — see LICENSE.