Package Exports
- @x12i/graph-composer
Readme
@x12i/graph-composer
| Location | |
|---|---|
| GitHub (source) | woroces/graph-composer — clone: git@github.com:woroces/graph-composer.git |
| npm (package) | @x12i/graph-composer |
The Git repo lives under the woroces org with repo name graph-composer. That is separate from the npm scope @x12i.
LLM-backed graph composer for the worox-graph DAG format: create, modify, explain, or suggestConceptObjective (primary intent / graph-level objective for metadata.graphConcept) using aifunctions-js and OpenRouter.
Architecture (two ways to run)
Direct workers (
runGraphComposer) — You setintent.action. Each action uses a dedicated system prompt (shared worox-graph fragments + oneaction-*.mdfile) plus the same skill catalogs and skill-mode gate as before. All graph-scoped actions are registered insrc/graphComposerActions.ts; adding an action means extending that registry and adding prompt files (seefunctions/graph-composer/prompts/README.md).Orchestrator (
runGraphComposerAgent) — You pass a natural-languagegoal. The orchestrator usesrunJsonCompletion(structured JSON steps) to choose registered tools (graph_create,graph_modify,graph_explain,graph_suggest_concept_objective), then runs each selection via the samerunGraphWorkerpath as direct mode. This costs more tokens and latency (multiple LLM rounds) than a single direct call.
Upstream feature request for first-class tool loops / worker profiles in aifunctions-js: docs/aifunctions-agent-toolbox-feature-request.md.
Install
npm install @x12i/graph-composerRequires Node.js 18+.
Environment
| Variable | Required | Description |
|---|---|---|
OPENROUTER_API_KEY |
Yes (for API runs) | OpenRouter API key. |
LLM_MODEL_STRONG |
No | Model slug when using mode: "strong" (default preset from aifunctions-js). |
LLM_MODEL_NORMAL |
No | Model slug for normal mode. |
GRAPH_COMPOSER_LOGS_LEVEL |
No | Log level for logs-gateway (info, warn, …). |
Copy .env.example to .env for local development. Do not commit secrets.
Quick start (direct worker)
import { runGraphComposer } from "@x12i/graph-composer";
const result = await runGraphComposer(
{
intent: {
action: "create",
description: "Read a record, classify it, persist the result.",
},
skillMode: "locked",
aiSkills: [
{
skillKey: "professional-answer",
description: "Structured analysis with LLM",
isLocal: false,
},
],
utilitySkills: [
{
skillKey: "scoped-data-reader",
description: "Read scoped data",
isLocal: true,
},
{
skillKey: "scoped-answer-writer",
description: "Persist results",
isLocal: true,
},
],
constraints: { requireFinalizer: true },
},
{
askTimeoutMs: 120_000,
connectTimeoutMs: 60_000,
maxTokens: 8192,
}
);Orchestrator (toolbox)
import { runGraphComposerAgent } from "@x12i/graph-composer";
const out = await runGraphComposerAgent(
{
goal:
"Explain the attached graph for operators: summary, execution order, data flow.",
existingGraph: myGraphJson,
skillMode: "locked",
aiSkills: [...],
utilitySkills: [...],
},
{
askTimeoutMs: 120_000,
connectTimeoutMs: 60_000,
maxTokens: 8192,
maxOrchestratorSteps: 8,
}
);
// out.orchestration.summary — orchestrator narrative
// out.orchestration.steps — which tools ran
// out.result — last worker JSON (e.g. explain payload)runGraphComposerAgent uses the same OpenRouter client resolution as workers; pass options.model if you need an explicit model for orchestrator JSON steps (see aifunctions-js runJsonCompletion).
Explain an existing graph
Pass existingGraph (worox-graph JSON) and intent.action: "explain".
Suggest primary intent (suggestConceptObjective)
Generic API (any graph): set intent.action: "suggestConceptObjective", existingGraph (required), optional analysisContext, and the usual skill / constraint fields. This is not tied to a specific domain or subnet.
Bundled example only: inputSuggestConceptObjectiveNetworkVulnSubnet() and the sample graph under examples/ are fixtures for tests and docs—they illustrate one real graph, not a special-case API.
Optional intent.onlyIfEmpty: array of patch field names (primaryIntentType, primaryIntentStatement, businessObjective, primaryOutcome). The runtime drops any listed key from the model’s graphConceptPatch when existingGraph.metadata.graphConcept.<key> is already a non-empty string, and appends a short note to rationale when something was skipped.
Stable result shape (top-level, in addition to action):
{
"action": "suggestConceptObjective",
"graphConceptPatch": {
"primaryIntentType": "objective",
"primaryIntentStatement": "One or two product-facing sentences describing what this graph achieves for the user.",
"businessObjective": "",
"primaryOutcome": ""
},
"rationale": "Optional short note for UI or logs."
}primaryIntentType is one of: question, decision, action, objective (same vocabulary as playground INTENT_TYPE_OPTIONS). Apply the patch in the consumer with a shallow merge into metadata.graphConcept, e.g. { ...existing, ...graphConceptPatch }.
Types: GraphConceptPatch, GraphConceptPatchKey, PrimaryIntentType. Helper: applyGraphConceptPatchOnlyIfEmpty() (same merge rule the runtime uses after the LLM returns).
Example using the bundled fixture helper:
import { runGraphComposer, inputSuggestConceptObjectiveNetworkVulnSubnet } from "@x12i/graph-composer";
const result = await runGraphComposer(inputSuggestConceptObjectiveNetworkVulnSubnet(), {
askTimeoutMs: 120_000,
connectTimeoutMs: 60_000,
maxTokens: 4096,
});CLI (after install)
Core usage: pass a test-cases.json id (e.g. explain-basic, create-simple-linear) — these map to the pack’s machine fixtures.
Demo / smoke only (not the core API surface):
network-vuln— runs explain on the bundled subnet triage sample graph.network-vuln-intent— runssuggestConceptObjectiveon the same sample graph.
export OPENROUTER_API_KEY=sk-or-...
npx @x12i/graph-composer explain-basic
npx @x12i/graph-composer network-vulnOr use the binary name:
graph-composer explain-basicAPI highlights
| Export | Purpose |
|---|---|
runGraphComposer(input, options?) |
Direct worker for intent.action. |
runGraphComposerAgent(input, options?) |
Orchestrator + toolbox (multi-step JSON). |
runGraphWorker |
Same LLM path as runGraphComposer (used internally and for advanced composition). |
getGraphComposerLlmClient |
Always returns an OpenRouter Client (orchestrator / custom ask use). |
resolveGraphComposerClient |
Optional client + timeout wiring (may return undefined for executeSkill defaults). |
GRAPH_COMPOSER_ACTION_REGISTRY, getActionDefinition, … |
Extensible action registry + prompt paths. |
composeWorkerInstructions |
Build full system text for one action + catalogs + mode gate. |
applyGraphConceptPatchOnlyIfEmpty |
Apply intent.onlyIfEmpty rules to a graphConceptPatch. |
composeInstructions, formatSkillList |
Lower-level composition from a raw base string + skill lists. |
getPackDir() |
Absolute path to the bundled functions/graph-composer pack. |
graphComposerPackRoot() |
Same path as getPackDir(). |
readGraphComposerPromptFile(name) |
Read a file under functions/graph-composer/prompts/. |
DEFAULT_UTILITY_SKILLS |
Default local skills when utilitySkills is omitted. |
RunGraphComposerOptions includes client, mode, model, temperature, maxTokens, askTimeoutMs, and connectTimeoutMs — see integration handoff.
Bundled content
Published tarball includes:
dist/— compiled ESM + TypeScript declarationsfunctions/graph-composer/—prompts/(per-action workers,shared/,orchestrator-system.md,judge-rules.md+ JSON block,default-utility-skills.json), plusmeta.json,test-cases.jsonexamples/network-vuln-subnet-triage.v2.json— sample worox graph
It does not include internal docs/, tests, or .env.
Development (this repo)
The repository may keep a duplicate of the sample graph under docs/examples/ for documentation. The published package only ships examples/; keep them in sync if you change the sample.
cp .env.example .env
npm install
npm run build
npm run verify:local
npm run typecheck
npm test # live tests; needs OPENROUTER_API_KEY in .envOptional: nx-config2 for scripts that load .env:
npx nx-config2 run --env-file .env -- npm testMaintainer smoke (suggest only, truncated JSON): npm run suggest-smoke (repo only; uses scripts/run-suggest-concept-smoke.ts).
Documentation in this repo
- Handoff / forward notes: docs/integration-handoff.md
- aifunctions-js agent toolbox FR: docs/aifunctions-agent-toolbox-feature-request.md
- Verify suggestConceptObjective: docs/verify-suggest-concept-objective.md
- aifunctions-js transport report: docs/report-aifunctions-js-undici-http.md
- Historical spec: docs/specs.md — not published on npm
Publishing (maintainers)
Scoped package @x12i/graph-composer uses publishConfig.access: "public". Ensure your npm user is a member of the x12i org (or owns the scope) and has a valid token in ~/.npmrc or project .npmrc (never commit tokens).
npm run build
npm publishConfirm tarball: npm run pack:check (must not list docs/, .env, or test/).
License
MIT — see LICENSE.