Skip to content

AgentGenerator Output Assembly Contract

Status: CANONICAL — describes what actually exists Last verified: 2026-09-29 Source files: - factory_app/workflows/AgentGenerator/tools/generate_and_download.py - factory_app/workflows/AgentGenerator/tools/workflow_converter.py - factory_app/workflows/AgentGenerator/structured_outputs.yaml - factory_app/workflows/AgentGenerator/agents.yaml - factory_app/workflows/AgentGenerator/extended_orchestration/task_batches.yaml

Related: structured-output-extraction-contract.md — the general runtime contract for structured outputs and auto-tool-call. This document covers the AgentGenerator-specific pattern where a task batch worker agent produces all workflow bundle files in a single structured output.


How This Works

AgentGenerator first validates and reviews the workflow partition:

  1. PatternAgent emits PatternSelection. Its tool validates the typed selection against the canonical DesignDocs workflow surface map before writing workflows_spec. Module pricing selections are validated by the subscription designer and AppGenerator with their data contract; AgentGenerator does not revalidate them.
  2. Invalid selections return validation feedback to PatternAgent. Three total selection attempts are permitted per run; exhausted attempts fail rather than dispatching an invalid plan.
  3. ProjectOverviewAgent presents WorkflowPlanReview, except for a validated empty partition in explicit autonomous mode. Approval, request-changes, and cancellation are structured UI responses correlated by review_id and the exact selection hash. Chat keywords cannot approve a plan.
  4. For an approved non-empty partition, PackBuildCoordinator starts workflow_generation_tasks: one WorkflowBundleBuilderAgent per workflow.
  5. Each worker emits WorkflowBundleBuilderOutput containing CodeFile entries. The runtime collects results in workflow_bundle_results, keyed by task ID.
  6. generate_and_download validates the resulting workflow contracts before writing accepted bundles, creating the ZIP, or presenting the download UI.

Workflow features are excluded from generated pricing until workflow launch enforces plan grants (#770). AgentGenerator rejects a saved contract that still selects a workflow pricing feature and asks for SubscriptionContractDesigner to rerun. Unpriced workflows continue using the workflow name capability convention for event routing.

Apps Without AI Workflows

An explicit workflows: [], is_multi_workflow: false, and non-empty pack_partition_reason is valid when the approved design requires only modules and pages. A missing or malformed selection is not equivalent to this decision. Unknown surface kinds and contradictions with DesignDocs fail validation.

When coding_participation is exactly autonomous, the validated empty partition records workflow_plan_review.status: not_required with its selection hash and rationale, without requesting or claiming human approval. Other modes retain the review. After that decision or human approval, the existing artifact recorder saves a workflow_bundle build record with workflows: [], the review disposition, and no workflow ZIP, primary workflow, API endpoint, or websocket endpoint. The stage completes only after this required save succeeds. It does not run the task batch or fabricate a workflow. Downstream AppGenerator consumes the same explicit empty integration metadata; prior workflow hints are cleared.

Review changes return to PatternAgent; at most three review attempts are allowed, with retries only after changes_requested. These limits are runtime execution guards, not freemium or subscription entitlements. Cancellation, stale approval, failed recording, and exhausted attempts fail the stage.

There are no sequential planning agents scraping MongoDB. Each WorkflowBundleBuilderAgent instance owns its full bundle output end-to-end.

Generated workflow bundles are staged at:

$MOZAIKS_GENERATED_ARTIFACTS_PATH/workflows/{app_id}/{build_id}/{workflow_name}/

They do not become active runtime-loaded workflows until an explicit promotion step copies them into an active app root's workflows/ directory.


Agent Roster

Agent Role
InterviewAgent Clarifies missing AI requirements without inventing automation
PatternAgent Selects zero, one, or multiple workflows inside the approved design boundary
ProjectOverviewAgent Presents the draft-correlated workflow plan review
PackBuildCoordinator Starts the task batch for an approved non-empty partition
WorkflowBundleBuilderAgent Task batch worker — generates all YAML and code files for one workflow bundle
PackMetadataAgent Produces pack-level extension_registry.json metadata after workflow bundles complete
DownloadAgent Triggers generate_and_download after pack metadata is ready

Task Batch: workflow_generation_tasks

Declared in extended_orchestration/task_batches.yaml.

source:
  kind: context_variable
  path: workflows_spec
  task_model: WorkflowInPack
worker:
  mode: ag2_agent
  agent_field: initial_agent   # WorkflowBundleBuilderAgent
  prompt_field: initial_message
result:
  context_key: workflow_bundle_results
  status_key: workflow_bundle_status

Each task receives one WorkflowInPack entry from workflows_spec. Its optional design_surface_id references the approved DesignDocs workflow surface. The runtime injects it as context_variables["structured_output"] for the worker.


WorkflowBundleBuilderOutput

The serialized YAML inside each orchestrator.yaml file must declare top-level schema_version: mozaiks.orchestrator.v1; each structured_outputs.yaml file must declare schema_version: mozaiks.structured_outputs.v1. The assembler validates these document versions; the outer bundle is not their authority.

The worker emits a single WorkflowBundleBuilderOutput structured output:

workflow_name: str
outcome_plans: []
files:
  - filename: orchestrator.yaml
    content: "..."
  - filename: agents.yaml
    content: "..."
  - filename: transition_graph.yaml
    content: "..."
  - filename: context_variables.yaml
    content: "..."
  - filename: structured_outputs.yaml
    content: "..."
  - filename: tools.yaml
    content: "..."
  - filename: middleware.yaml
    content: "..."
  - filename: ui_config.yaml
    content: "..."
  - filename: tools/some_tool.py
    content: "..."
  - filename: ui/index.js
    content: "..."

Each CodeFile has: - filename — workflow-local relative path (e.g., tools/save_result.py, ui/index.js) - content — full file content as a string

The outer structured response does not validate the YAML or Python inside content. The quality gate parses all eight required workflow documents, plus optional a2a.yaml, through the same schema parsers used by the runtime. It also checks context references, transition compilation, and task-batch contracts. Duplicate filenames, retired declarative JSON/YML variants, and unrendered .j2 files block export.

Declared tools must have an included Python file and matching top-level function. Python syntax errors and unfinished tool implementations block export. Workers must implement the tool behavior; there is no later tool-implementation stage. These static checks do not prove arbitrary business logic or external integrations work. Functional execution tests remain necessary for those behaviors.

outcome_plans is a typed list of operation plans. Each plan names agent, function, context_key, attempts_key, result_field, error_value, max_attempts, retry_on, and routes: [{value, target_agent}]. Use an empty list only when no operation needs outcome-dependent routing. Business-specific outcomes are allowed; every outcome must have one known destination.

outcome_materialization.py deterministically generates the matching tool outcome binding, protected context definitions, and ordinary graph transitions. Workers omit these owned context definitions and source-agent transitions from their raw files. They still generate the operation's implementation, tool binding, agent definition, and structured input model. Quality gates validate the materialized files; downloads contain those files, not a runtime dependency on Factory or its build-time plans. Hand-authored workflows use the same runtime tools[].outcome contract documented in Workflow Authoring Contracts.


workflow_bundle_results Structure

After the task batch completes, context_variables["workflow_bundle_results"] is a dict:

{
    "task_id_1": {
        "workflow_name": "StoryCreator",
        "files": [
            {"filename": "orchestrator.yaml", "content": "..."},
            {"filename": "agents.yaml", "content": "..."},
            ...
        ]
    },
    "task_id_2": {
        "workflow_name": "ReviewWorkflow",
        "files": [ ... ]
    }
}

Keys starting with _ are internal meta entries and are skipped during assembly.


Assembly: generate_and_download

Reads workflow_bundle_results directly from context. For each bundle entry:

  1. Materialize operation plans and validate the resulting workflow contracts.
  2. On failure, schedule bounded workflow repair or return to user attention.
  3. _write_bundle_to_disk(wf_name, files, base_dir) writes accepted files under base_dir/{wf_name}/.
  4. _build_pack_zip(bundle_dirs, output_path) zips the workflow directories.
  5. use_ui_tool("DownloadCenter", ...) presents the download UI.

Assembly reads task-batch structured outputs directly from runtime context.

Workflow Integration Metadata

During bundle assembly, generate_and_download derives workflow_integration_metadata from each generated workflow's orchestrator.yaml:

  • workflow_name
  • derived stable capability_id
  • workflow_startup_mode
  • event triggers from the triggers[] block

The normalized metadata is written back to context as:

  • workflow_integration_metadata
  • generated_workflow_integrations
  • generated_workflow_name
  • generated_workflow_capability_id
  • generated_workflow_startup_mode
  • generated_workflow_trigger_events

AgentGenerator persists the same metadata on the workflow_bundle artifact. AppGenerator hydrates it from the latest current workflow_bundle artifact before agents run, then its deterministic acceptance gate blocks export unless the generated app wires the workflow through module capabilities, emitted events, and contracts/reactions.yaml.

Smoke coverage:

python scripts/smoke_factory_artifact_lineage.py
python scripts/smoke_factory_artifact_lineage.py --real-store
python scripts/smoke_factory_artifact_lineage.py --real-store --live-agentgenerator --timeout-seconds 600

The first command runs the deterministic in-memory chain. The second uses the Mongo-backed ArtifactStore. The third runs live AgentGenerator AG2 calls, persists the live workflow metadata through the real artifact store, hydrates AppGenerator from that workflow_bundle, and verifies app acceptance/export and runtime loader reaction wiring.

generate_and_download runs the workflow bundle quality gate before download, artifact registration, zip creation, or promotion. The gate writes workflow_bundle_validation_status, workflow_bundle_validation_errors, and workflow_bundle_semantic_drift to context. Blocking failures return status: blocked; the generated bundle is not packaged.

When blocking failures map to specific workflows, generate_and_download schedules a bounded repair pass instead of broad regeneration. It writes workflow_bundle_repair_status: needs_revision, increments workflow_bundle_repair_count, preserves the full pre-repair workflow_bundle_results, narrows workflows_spec to the failed workflow specs, and routes back to PackBuildCoordinator. Each repaired worker receives the exact quality-gate failures in its scoped initial_message. After the repair task batch completes, WorkflowBundleMergeAgent invokes the deterministic merge_workflow_bundle_repair_results auto tool. It commits repaired workflow outputs together with the preserved successful outputs and restores the complete workflows_spec before PackMetadataAgent generates metadata and packaging runs again. The merge is not a prompt hook: workflow_bundle_results requires an authorized writer. Only a committed merged status advances to metadata; a refused write cannot report success. After the configured attempt limit, the status becomes blocked and the workflow returns to the user.

The live AgentGenerator pack smoke also emits the same semantic_drift report. That report is intentionally prompt-oriented: it flags generated workflow YAML that loads but no longer preserves the requested workflow meaning, such as event triggers with missing capability_id, generic trigger descriptions, or conveyor workflows that collapse downstream parallel work into one execution agent. Conveyor workflows that represent heavy downstream work must declare at least two distinct execution agents in extended_orchestration/task_batches.yaml; repeating the same worker name is semantic drift. Fix those failures in AgentGenerator prompt or structured-output contracts first, then rerun the live smoke.

Files Written

$MOZAIKS_GENERATED_ARTIFACTS_PATH/workflows/{app_id}/{build_id}/
├── {WorkflowName}/
│   ├── orchestrator.yaml
│   ├── agents.yaml
│   ├── transition_graph.yaml
│   ├── context_variables.yaml
│   ├── structured_outputs.yaml
│   ├── tools.yaml
│   ├── middleware.yaml
│   ├── ui_config.yaml
│   ├── extended_orchestration/
│   │   └── task_batches.yaml   ← if workflow uses task batches
│   ├── tools/
│   │   └── *.py               ← tool implementations
│   └── ui/
│       ├── index.js            ← component barrel
│       └── *.jsx               ← workflow-local React components
└── {PackName}.zip             ← all workflows bundled together

Generated workflow tools are workflow-local. Generated bundles must not reference workflows/_shared, sibling workflow tool folders, or root-level shared paths. Reusable framework-owned support code belongs under mozaiksai.core.*.


Workflow Name and Pack Name

  • bundle_name is derived from context_variables["pack_name"] if set, otherwise from the first workflow's workflow_name
  • All names are converted to PascalCase for the output folder and zip file name

Normalization Utilities in workflow_converter.py

workflow_converter.py is a contract normalization helper — it does NOT do assembly. Functions exported:

Function Purpose
promote_generated_workflow(source_dir, target_root) Copy a generated workflow into the active workflows root
_normalize_transition_rules(raw_rules) Normalize transition rule list; rejects LLM-evaluated conditions
_normalize_tools_manifest(output, wf_logger) Normalize tools + lifecycle_tools with UI realization stamps
_normalize_visual_agents(value, workflow_startup_mode) Normalize visual_agents list per workflow_startup_mode
_collect_ui_code_files(output, tools_config, wf_logger) Collect UIFileGenerator output, skip shipped primitives, synthesize barrel
_normalize_runtime_extensions(extensions, workflow_name, wf_logger) Keep extensions workflow-local
_normalize_orchestrator_triggers(triggers, wf_logger) Validate trigger types against declared schema

These are used by tests and by WorkflowBundleBuilderAgent implementations as reference for what a well-formed bundle looks like.


Current Boundaries

AgentGenerator's runtime path is a compact task-batch workflow:

  • PatternAgent selects the workflow topology and AG2 network pattern.
  • ProjectOverviewAgent presents the generated-workflow plan for review.
  • PackBuildCoordinator triggers workflow_generation_tasks.
  • WorkflowBundleBuilderAgent workers generate complete workflow bundles in parallel.
  • WorkflowBundleMergeAgent restores the full workflow set after a repair batch.
  • PackMetadataAgent generates pack-level routing metadata.
  • DownloadAgent packages the generated artifacts.

Bundle assembly is context-first: generated workflow files come from workflow_bundle_results, and pack metadata comes from the current structured outputs. Runtime loading still requires explicit promotion into an active workspace workflow root.


Cross References

  • structured-output-extraction-contract.md — general auto-tool-call pattern
  • workflow-authoring-contracts.md — extended_orchestration/task_batches.yaml format
  • factory_app/workflows/AgentGenerator/tools/generate_and_download.py — assembly and download
  • factory_app/workflows/AgentGenerator/tools/workflow_converter.py — normalization utilities
  • factory_app/workflows/AgentGenerator/extended_orchestration/task_batches.yaml — task batch config
  • factory_app/workflows/AgentGenerator/structured_outputs.yaml — WorkflowBundleBuilderOutput model