# https://github.com/hanyeol/model-compose Project Manual

Generated at: 2026-07-04 05:38:38 UTC

## Table of Contents

- [Introduction and Core Philosophy](#page-introduction)
- [Component System and Architecture](#page-components)
- [Workflow Composition, Jobs and Streaming](#page-workflows)
- [Deployment, Runtimes, and Protocol Adapters](#page-deployment)

<a id='page-introduction'></a>

## Introduction and Core Philosophy

### Related Pages

Related topics: [Component System and Architecture](#page-components), [Workflow Composition, Jobs and Streaming](#page-workflows), [Deployment, Runtimes, and Protocol Adapters](#page-deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/hanyeol/model-compose/blob/main/README.md)
- [pyproject.toml](https://github.com/hanyeol/model-compose/blob/main/pyproject.toml)
- [src/mindor/__init__.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/__init__.py)
- [src/mindor/dsl/schema/compose.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/dsl/schema/compose.py)
- [docs/user-guide/02-core-concepts.md](https://github.com/hanyeol/model-compose/blob/main/docs/user-guide/02-core-concepts.md)
- [docs/user-guide/01-getting-started.md](https://github.com/hanyeol/model-compose/blob/main/docs/user-guide/01-getting-started.md)
- [src/mindor/dsl/schema/component.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/dsl/schema/component.py)
- [src/mindor/dsl/schema/job.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/dsl/schema/job.py)
</details>

# Introduction and Core Philosophy

## What is model-compose

`model-compose` is a Python-based framework for composing and orchestrating AI/ML workflows from small, reusable building blocks. Instead of writing monolithic pipelines, users declare a workflow as a *compose* description — a declarative schema that wires together **components** (units that perform an action, such as calling a model or running an HTTP request) and **jobs** (orchestration units that schedule or chain work). The framework then interprets that description, starts the required services, and exposes the assembled workflow as a runnable target such as an MCP server, a streaming endpoint, or a containerized controller.

The project lives under the Python package namespace `mindor` (see `src/mindor/__init__.py`), and the project metadata in `pyproject.toml` describes it as a toolkit for building modular, model-driven workflows. Source: [pyproject.toml:1-40]()

At its heart, `model-compose` treats every interaction with a model, API, shell, or local script as a *component* that can be referenced by name and reused across multiple workflows. This composition-first mindset is what the rest of this wiki page unpacks.

## Core Philosophy and Design Principles

The framework is built around a small set of recurring principles that recur across its release history and its schema definitions:

- **Declarative composition over imperative glue code.** A workflow is described as data, not as a sequence of function calls. The top-level schema in `src/mindor/dsl/schema/compose.py` defines the `Compose` model that anchors the entire description, and every other schema (components, jobs, services) hangs off it. Source: [src/mindor/dsl/schema/compose.py:1-80]()
- **Components as first-class citizens.** Each capability — calling an LLM, executing a shell command, exposing an HTTP server, running local inference — is encapsulated in its own component schema. The component type registry lives in `src/mindor/dsl/schema/component.py`, where each component declares its own configuration, inputs, and outputs. Source: [src/mindor/dsl/schema/component.py:1-60]()
- **Jobs coordinate, components act.** Jobs (`src/mindor/dsl/schema/job.py`) describe *when* and *how* work runs — schedules, triggers, dependencies — without knowing the internal mechanics of any component. This separation lets users swap implementations without rewriting orchestration. Source: [src/mindor/dsl/schema/job.py:1-60]()
- **Multiple deployment targets from one description.** The same compose file can be deployed as an MCP server, a streaming service, a Docker controller, or a local process. The README and the user guide position this flexibility as a core reason to use the project. Source: [README.md:1-80]()

These principles are reflected concretely in the user documentation: `docs/user-guide/02-core-concepts.md` introduces the mental model of *compose → components → jobs* before any concrete syntax is shown. Source: [docs/user-guide/02-core-concepts.md:1-60]()

## Version Evolution and the Growing Component Ecosystem

The community release notes show a clear philosophical arc — each stable release expands the set of plug-in components while preserving the same declarative schema.

| Release | Theme | Key Additions |
|---------|-------|---------------|
| v0.1.0 | Initial stable release | Core schema, basic components, README |
| v0.2.0 | Production-oriented deployment | MCP server deployment, shell command components |
| v0.3.0 | Local model integration | Local model inference component, Docker-based controller |
| v0.4.0 | Real-time and HTTP workflows | Streaming/event-stream modes, HTTP server component |

This progression shows that the maintainers prioritize *backwards-compatible extensibility*: every release adds new component types without removing earlier ones. Source: [README.md:1-120]()

## Architectural Overview

The runtime resolves a compose file by reading the declarative schema, instantiating the declared components and jobs, and wiring their inputs and outputs together. The high-level flow looks like this:

```mermaid
flowchart LR
    A[Compose YAML/Schema] --> B[Schema Parser]
    B --> C[Component Registry]
    B --> D[Job Registry]
    C --> E[Runtime Instances]
    D --> E
    E --> F{Mode}
    F --> G[MCP Server]
    F --> H[Streaming Service]
    F --> I[Docker Controller]
    F --> J[Local Process]
```

The schema parser, anchored by `Compose` in `compose.py`, normalizes the user input; the registries then look up each named component and job type and construct the appropriate runtime. Source: [src/mindor/dsl/schema/compose.py:1-80](), [src/mindor/dsl/schema/component.py:1-60](), [src/mindor/dsl/schema/job.py:1-60]()

For newcomers, `docs/user-guide/01-getting-started.md` walks through the first end-to-end example — declaring a compose file, running it locally, and exposing it via the chosen deployment mode — which is the recommended entry point before diving into component-specific documentation. Source: [docs/user-guide/01-getting-started.md:1-80]()

## Summary

`model-compose` is best understood as a *declarative composition layer* on top of heterogeneous model and service runtimes. Its philosophy can be summarized in three sentences: describe workflows as data, treat every capability as a named component, and let the same description run anywhere the framework supports. The rest of the wiki — components, jobs, schema reference, deployment guides — elaborates on each of these themes in turn.

---

<a id='page-components'></a>

## Component System and Architecture

### Related Pages

Related topics: [Introduction and Core Philosophy](#page-introduction), [Workflow Composition, Jobs and Streaming](#page-workflows)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/mindor/core/component/component.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/component/component.py)
- [src/mindor/dsl/schema/component/component.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/dsl/schema/component/component.py)
- [src/mindor/core/component/runtime/docker.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/component/runtime/docker.py)
- [src/mindor/core/component/services/agent.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/component/services/agent.py)
- [docs/reference/compose/components/model.md](https://github.com/hanyeol/model-compose/blob/main/docs/reference/compose/components/model.md)
- [docs/reference/compose/components/agent.md](https://github.com/hanyeol/model-compose/blob/main/docs/reference/compose/components/agent.md)
</details>

# Component System and Architecture

## Overview

The **Component System** is the foundational abstraction of `model-compose`. It allows users to assemble workflows by composing modular building blocks — agents, models, HTTP servers, shell commands, and MCP servers — into a single, deployable pipeline. Each component encapsulates a self-contained unit of computation that can communicate with others through well-defined interfaces.

A component in `model-compose` is more than a simple function: it includes a runtime (such as Docker), a service implementation (such as an agent), and a configuration schema that is consumed at deployment time. This layered design enables the same logical component to be declared once in the DSL and executed in different environments without code changes. Source: [src/mindor/core/component/component.py]().

Across recent releases the component ecosystem has expanded significantly:

- **v0.2.0** introduced shell commands and MCP server deployment as first-class components. Source: [v0.2.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.2.0).
- **v0.3.0** added a **Local Model Inference Component** and **Docker-based Controller Deployment**, enabling inference from models stored locally and containerized execution. Source: [v0.3.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.3.0).
- **v0.4.0** expanded the ecosystem further with an **HTTP server component** and introduced **streaming** and **event-stream** modes for real-time interactions. Source: [v0.4.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.4.0).

## Layered Architecture

The component system follows a clear three-layer separation of concerns:

| Layer | Responsibility | Example Source |
|-------|----------------|----------------|
| **DSL Schema** | Declarative configuration and validation | `src/mindor/dsl/schema/component/component.py` |
| **Core Component** | Lifecycle, dispatch, and wiring between services and runtimes | `src/mindor/core/component/component.py` |
| **Runtime / Service** | Concrete execution: Docker containers, agent logic, model inference | `src/mindor/core/component/runtime/docker.py`, `src/mindor/core/component/services/agent.py` |

The DSL layer validates user-authored definitions; the core layer orchestrates the lifecycle of each declared component; the runtime and service layers provide the actual implementation. This separation means that swapping a Docker runtime for a different runtime — or replacing one service implementation with another — does not affect the configuration layer. Source: [src/mindor/core/component/component.py](), [src/mindor/dsl/schema/component/component.py]().

### Component Lifecycle Flow

```mermaid
flowchart LR
    A[DSL Definition] --> B[Schema Validation]
    B --> C[Component Core]
    C --> D[Service Layer<br/>agent | model | http | shell]
    C --> E[Runtime Layer<br/>docker | local]
    D --> F[Execution]
    E --> F
```

The flow begins with a DSL definition that is validated against the schema, instantiated by the core, and then bound to a service and a runtime before execution. Source: [src/mindor/core/component/component.py](), [src/mindor/core/component/runtime/docker.py]().

## Component Types and Built-Ins

Each documented component type has its own reference page describing configuration keys, inputs, and outputs:

- **Model component** — performs inference using a model backend. The reference page covers configuration of model identifiers, parameters, and input/output contracts. Source: [docs/reference/compose/components/model.md]().
- **Agent component** — implements reasoning behavior on top of a model. Its reference page describes how agents are wired to model components and how they expose structured outputs. Source: [docs/reference/compose/components/agent.md](), [src/mindor/core/component/services/agent.py]().

Beyond these, the release history shows the available built-in inventory:

| Component | First Stable Release | Reference |
|-----------|---------------------|-----------|
| Agent | v0.1.0 | `docs/reference/compose/components/agent.md` |
| Model (local inference) | v0.3.0 | `docs/reference/compose/components/model.md` |
| MCP server deployment | v0.2.0 | release notes v0.2.0 |
| Shell command | v0.2.0 | release notes v0.2.0 |
| HTTP server | v0.4.0 | release notes v0.4.0 |
| Docker-based controller | v0.3.0 | release notes v0.3.0 |

The v0.4.0 release further extended the runtime contract with **event-stream** and **streaming modes**, which are expressed through the same component abstraction but alter how outputs flow back to the caller. Source: [v0.4.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.4.0).

## Configuration Through the DSL

Components are declared in the DSL and validated against the schema module. The schema module exposes the structure used to parse user-authored files and produce typed component instances, allowing the core to treat every component uniformly regardless of its concrete type. Source: [src/mindor/dsl/schema/component/component.py]().

In practice this means a typical user workflow:

1. Author one or more components in a DSL file, selecting the type and supplying required configuration.
2. The schema layer validates the file and produces typed objects.
3. The core instantiates each component, attaches a service implementation (for example `agent`), and binds a runtime (for example `docker`).
4. The workflow is executed; for MCP-style deployments the same component set can be exposed as an MCP server, a feature available since v0.2.0. Source: [v0.2.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.2.0).

## Streaming and Extensibility

The v0.4.0 release introduced **event-stream** and **streaming modes** directly into the component contract. Components that produce incremental output can now advertise this capability, and the runtime layer is responsible for delivering intermediate events rather than only a final result. This change is fully backward compatible — components that do not declare streaming behavior continue to return a single response. Source: [v0.4.0 release notes](https://github.com/hanyeol/model-compose/releases/tag/v0.4.0).

New component types can be added without modifying the core by implementing the runtime and service contracts and registering a corresponding schema entry. The Docker runtime in particular serves as a reference implementation for any container-based component. Source: [src/mindor/core/component/runtime/docker.py]().

## Summary

The Component System provides the modular backbone of `model-compose`. It cleanly separates declarative configuration (DSL/schema), lifecycle orchestration (core), and execution (service + runtime). Built-in components have grown steadily — from agents in v0.1.0, through MCP servers and shell components in v0.2.0, local model inference and Docker controller deployment in v0.3.0, to HTTP servers and streaming/event-stream modes in v0.4.0 — and the same architectural pattern accommodates each new addition without breaking existing workflows.

---

<a id='page-workflows'></a>

## Workflow Composition, Jobs and Streaming

### Related Pages

Related topics: [Component System and Architecture](#page-components), [Deployment, Runtimes, and Protocol Adapters](#page-deployment)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/mindor/core/workflow/workflow.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/workflow/workflow.py)
- [src/mindor/core/workflow/job/job.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/workflow/job/job.py)
- [src/mindor/core/workflow/job/impl/if_.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/workflow/job/impl/if_.py)
- [src/mindor/core/workflow/job/impl/for_each.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/workflow/job/impl/for_each.py)
- [src/mindor/core/workflow/job/impl/switch.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/workflow/job/impl/switch.py)
- [src/mindor/core/foundation/streaming/base.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/foundation/streaming/base.py)
</details>

# Workflow Composition, Jobs and Streaming

## Overview

`model-compose` organizes AI/LLM pipelines as declarative **workflows** built from reusable **components**, with execution driven by a tree of **jobs**. A workflow describes the data flow between components, while jobs provide imperative control flow (branching, iteration, dispatch) that wires those components together. Starting with v0.4.0, workflows can also expose results through two streaming modes — **event-stream** and **streaming** — enabling real-time interaction with HTTP clients and the MCP server runtime.

The composition model lives under `src/mindor/core/workflow/`, with the orchestration primitives implemented as job types under `src/mindor/core/workflow/job/` and the streaming layer under `src/mindor/core/foundation/streaming/`.

Source: [src/mindor/core/workflow/workflow.py:1-58]()
Source: [src/mindor/core/workflow/job/job.py:1-42]()

## Workflow Composition

A workflow is the top-level artifact users define. It is parsed from configuration, validated against the component registry, and compiled into a directed graph whose nodes are component instances and whose edges carry typed payloads. The root `Workflow` object owns the lifecycle (start, run, stop) and delegates per-node execution to the job tree.

Key responsibilities of `workflow.py`:
- Loading and validating workflow YAML/JSON definitions
- Instantiating component instances by type identifier (HTTP server, shell, local model, MCP, etc.)
- Resolving input/output bindings between components
- Scheduling the initial job and propagating results downstream

Source: [src/mindor/core/workflow/workflow.py:60-134]()

```mermaid
flowchart TD
    W[Workflow Root] --> J0[Initial Job]
    J0 --> C1[Component A]
    J0 -->|if_ branch| J1[If-Job]
    J0 -->|for_each iteration| J2[ForEach-Job]
    J1 -->|switch case| J3[Switch-Job]
    J2 --> C2[Component B]
    J3 --> C3[Component C]
    C1 --> S[(Streaming Sink)]
    C2 --> S
    C3 --> S
```

## Job System

Jobs are the imperative control layer that sits between declarative wiring and component execution. The abstract `Job` class defines `setup()`, `run()`, and `teardown()` hooks and tracks shared state such as inputs, outputs, and error context. Three control-flow implementations ship in v0.4.0:

### `if_` Job
Evaluates a boolean expression against the workflow context and routes execution to one of two downstream branches. It supports nested expressions and short-circuit evaluation, making it suitable for guards and fallback paths.

Source: [src/mindor/core/workflow/job/impl/if_.py:18-71]()

### `for_each` Job
Iterates over a collection value in the context and spawns a sub-execution for each element. Each iteration runs in an isolated context but shares the parent workflow's component bindings, enabling map-style fan-out over arrays produced by upstream components.

Source: [src/mindor/core/workflow/job/impl/for_each.py:22-88]()

### `switch` Job
Dispatches to one of N branches based on a key or value match. Unlike `if_`, `switch` is designed for multi-way routing (e.g., routing model inference by provider or routing HTTP requests by path) and returns the resolved branch's output as its own.

Source: [src/mindor/core/workflow/job/impl/switch.py:19-64]()

All three job types inherit the base `Job` lifecycle from `job.py`, which centralizes error propagation and ensures failed jobs surface as structured errors rather than silent drops.

Source: [src/mindor/core/workflow/job/job.py:44-119]()

## Streaming Support

v0.4.0 introduced first-class streaming so workflows can deliver incremental results instead of waiting for terminal completion. The streaming foundation is defined in `src/mindor/core/foundation/streaming/base.py`, which exposes a transport-agnostic `StreamBase` interface with `emit()`, `close()`, and async iteration support.

Two transport modes are exposed to clients:

| Mode | Transport | Use Case |
|------|-----------|----------|
| **event-stream** | Server-Sent Events (SSE) | MCP server, web clients that consume SSE deltas |
| **streaming** | HTTP chunked transfer | Generic HTTP clients and the new HTTP server component |

Both modes are wired through the same `StreamBase`, meaning any component that yields incremental tokens — including the local model inference component introduced in v0.3.0 and the HTTP server component added in v0.4.0 — can be surfaced through either transport without component-side changes.

Source: [src/mindor/core/foundation/streaming/base.py:1-96]()
Source: [src/mindor/core/foundation/streaming/base.py:98-160]()

The MCP server deployment (introduced in v0.2.0) consumes the **event-stream** mode to push model tokens into MCP clients in real time, while the HTTP server component (v0.4.0) consumes the **streaming** mode for plain HTTP consumers.

## Integration Patterns

Jobs and streaming compose naturally: a `switch` job can route a request to different model backends, each of which streams its response through the shared `StreamBase`. Similarly, `for_each` can fan out a prompt across multiple model components and merge their streams into a single SSE channel. Because the streaming interface is decoupled from component internals, future releases can add new transports (for example, WebSocket) by extending `StreamBase` alone, without touching the job layer.

Source: [src/mindor/core/workflow/job/impl/switch.py:66-104]()
Source: [src/mindor/core/foundation/streaming/base.py:162-205]()

---

<a id='page-deployment'></a>

## Deployment, Runtimes, and Protocol Adapters

### Related Pages

Related topics: [Introduction and Core Philosophy](#page-introduction), [Workflow Composition, Jobs and Streaming](#page-workflows)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/mindor/core/controller/controller.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/controller/controller.py)
- [src/mindor/core/runtime/docker.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/runtime/docker.py)
- [src/mindor/core/runtime/native.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/runtime/native.py)
- [src/mindor/core/controller/adapters/services/http_server.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/controller/adapters/services/http_server.py)
- [src/mindor/core/controller/adapters/services/mcp_server.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/controller/adapters/services/mcp_server.py)
- [src/mindor/core/controller/webui/gradio/driver.py](https://github.com/hanyeol/model-compose/blob/main/src/mindor/core/controller/webui/gradio/driver.py)
</details>

# Deployment, Runtimes, and Protocol Adapters

The Deployment, Runtimes, and Protocol Adapters layer is the boundary in `model-compose` between a user-authored workflow and the outside world. Where the rest of the system describes *what* should run, this layer decides *where* it runs and *how* external systems talk to it. It is composed of three cooperating concerns: a `Controller` that owns lifecycle, two interchangeable `Runtime` backends (native process and Docker container), and a set of protocol adapters that expose the running workflow as MCP services, HTTP endpoints, or a Gradio web UI. Source: [src/mindor/core/controller/controller.py:1-80]().

## Controller Lifecycle and Runtime Selection

The `Controller` is the orchestrator that loads a workflow definition, selects a runtime, and brings the workflow up or down. It is invoked once a deployment manifest is resolved and is responsible for translating runtime-agnostic intent (start, stop, stream, serve) into runtime-specific calls. Source: [src/mindor/core/controller/controller.py:1-120]().

Runtime selection is abstracted behind a common interface so that the same controller code can target either a local Python process or a containerized environment. Each runtime implementation owns the concerns specific to its environment: process supervision and module imports for native, image build, container creation, and port mapping for Docker. Source: [src/mindor/core/runtime/native.py:1-90](), Source: [src/mindor/core/runtime/docker.py:1-120]().

### Native Runtime

The native runtime executes the workflow in the host Python interpreter. It is the lowest-friction target during development: no image to build, no container to start, and full access to local resources such as on-disk models. Source: [src/mindor/core/runtime/native.py:40-140](). The v0.3.0 release added a Local Model Inference component designed to run against this runtime, which is the canonical path for users who already have model weights on disk. Source: release notes v0.3.0.

### Docker Runtime

The Docker runtime packages the workflow, its Python dependencies, and any required models into a container. It is the production target introduced in v0.3.0 and the recommended way to deploy the controller itself. It handles image construction, container lifecycle, log streaming, and cleanup of orphaned containers. Source: [src/mindor/core/runtime/docker.py:60-200](). Because each runtime exposes the same call surface, moving from native to Docker is a configuration change rather than a code change.

## Protocol Service Adapters

Once a runtime is running a workflow, protocol adapters decide how clients reach it. Two service adapters ship in the core, and each presents the underlying workflow through an industry-standard wire format.

### MCP Server Adapter

The MCP (Model Context Protocol) server adapter lets a workflow be consumed by MCP-compatible agents as if it were a native tool. This is the deployment mode advertised in the v0.2.0 release, where workflows can be served directly as MCP servers. Source: [src/mindor/core/controller/adapters/services/mcp_server.py:1-160](). The adapter is responsible for mapping the workflow's component graph onto MCP tool definitions, handling the request/response framing, and keeping tool schemas in sync with the live workflow definition.

### HTTP Server Adapter

The HTTP server adapter exposes the same workflow surface over plain HTTP, making it reachable from curl, browsers, or any HTTP client. It was added alongside the v0.4.0 streaming support and is the path that enables event-stream and streaming modes for real-time interactions. Source: [src/mindor/core/controller/adapters/services/http_server.py:1-180](). Streaming semantics are expressed through the response framing rather than through a separate transport, which keeps the contract consistent with non-streaming calls.

## Web UI Driver and End-to-End Deployment

Not every consumer of a workflow is an agent or a programmatic client. The Gradio web UI driver provides an interactive surface where developers and end users can drive a workflow through a browser. Source: [src/mindor/core/controller/webui/gradio/driver.py:1-150](). It reuses the same controller entry points as the protocol adapters but renders results through Gradio components instead of wire formats.

The end-to-end flow ties these pieces together as follows: a manifest is parsed, the `Controller` selects a runtime (native or Docker), the runtime brings the workflow online, and one or more adapters/UI drivers are attached to expose it. Multiple adapters can coexist against a single running workflow, so the same deployment can simultaneously serve MCP tools, HTTP clients, and a Gradio UI without redeploying.

| Layer | Component | Primary Source | Release |
|---|---|---|---|
| Orchestration | Controller | `controller/controller.py` | v0.2.0+ |
| Runtime (dev) | Native | `runtime/native.py` | v0.1.0+ |
| Runtime (prod) | Docker | `runtime/docker.py` | v0.3.0+ |
| Service Adapter | MCP Server | `adapters/services/mcp_server.py` | v0.2.0+ |
| Service Adapter | HTTP Server | `adapters/services/http_server.py` | v0.4.0+ |
| Web UI | Gradio Driver | `webui/gradio/driver.py` | v0.2.0+ |

This layering is the reason users can mix deployment surfaces freely: the runtime answers "what process is running," while adapters answer "how the world reaches it." Known limitations carried over from earlier releases, such as insufficient log messages, affect observability across all adapters and remain orthogonal to runtime choice. Source: release notes v0.1.0, v0.2.0, v0.3.0, v0.4.0.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: hanyeol/model-compose

Summary: Found 6 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Capability evidence risk - Capability evidence risk requires verification.

## 1. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/hanyeol/model-compose

## 2. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/hanyeol/model-compose

## 3. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/hanyeol/model-compose

## 4. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/hanyeol/model-compose

## 5. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/hanyeol/model-compose

## 6. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/hanyeol/model-compose

<!-- canonical_name: hanyeol/model-compose; human_manual_source: deepwiki_human_wiki -->
