# LMC Messages in Open Interpreter: Format Specification and Parsing Guide

> Learn the LMC message format in Open Interpreter. Understand the role, type, and content keys for standardized AI communication and parsing.

- Repository: [Open Interpreter/open-interpreter](https://github.com/openinterpreter/open-interpreter)
- Tags: api-reference
- Published: 2026-03-05

---

**LMC (Language Model Computer) messages are Python dictionaries with `role`, `type`, `content`, and optional `format` keys that standardize communication between users, AI assistants, and computer subsystems in Open Interpreter.**

Open Interpreter utilizes a custom **LMC message format** to maintain structured conversations across its execution pipeline. Unlike standard chat APIs, this protocol explicitly distinguishes between conversational content and executable code while preserving execution context. The schema is formally defined in [`docs/protocols/lmc-messages.mdx`](https://github.com/openinterpreter/open-interpreter/blob/main/docs/protocols/lmc-messages.mdx) and implemented throughout the core interpreter logic.

## LMC Message Format Specification

An LMC message is a plain Python `dict` containing four standardized fields that define the message's origin, payload type, and content structure.

| Key | Description | Required |
|-----|-------------|----------|
| `role` | Message sender: `user`, `assistant`, or `computer` | Yes |
| `type` | Payload category: `message`, `code`, `console`, `image`, or `audio` | Yes |
| `content` | Actual payload data (string for text, list for image URLs) | Yes |
| `format` | Subtype qualifier: `python`, `output`, `base64`, etc. | No |

The `role` field determines which subsystem processes the message, while `type` and `format` control rendering and execution behavior. For example, a `computer` role with `type: console` indicates system output rather than user-facing text.

### Example LMC Message Structures

```python

# User query

{"role": "user", "type": "message", "content": "What is 2 + 2?"}

# Assistant generating Python code

{
    "role": "assistant",
    "type": "code",
    "format": "python",
    "content": "print(2+2)"
}

# Computer returning execution results

{
    "role": "computer",
    "type": "console",
    "format": "output",
    "content": "4"
}

# Final assistant response

{"role": "assistant", "type": "message", "content": "The answer is 4."}

```

## How LMC Messages Are Parsed

The parsing pipeline in [[`interpreter/core/core.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/core.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/core.py) transforms raw execution chunks into structured LMC messages through a multi-stage process.

### Receiving Raw Chunks

Computer subsystems stream discrete chunks during code execution, with each chunk representing a partial LMC message. These chunks arrive as dictionaries containing preliminary `role`, `type`, and `content` fields before final assembly.

### Start and End Flag Handling

The `_respond_and_store` method in [`core.py`](https://github.com/openinterpreter/open-interpreter/blob/main/core.py) monitors chunk boundaries using start and end flags. When consecutive chunks share identical `role`, `type`, and `format` values, the interpreter appends their content to a single accumulating message. When these attributes differ, the system emits an end flag for the previous message and a start flag for the new one.

```python

# Logic pattern from _respond_and_store in core.py

if last_flag_base and (same_role_type_format):
    # Append content to existing message

    current_message["content"] += new_chunk["content"]
else:
    # Emit end flag for previous, start flag for new

    finalize_previous_message()
    initialize_new_message()

```

The helper function `is_ephemeral` filters transient chunks such as `active_line` or `review` markers that should not persist in the final message history.

### Merging Chunks into Messages

Successive chunks with matching metadata are concatenated into unified LMC messages stored in `interpreter.messages`. This merging preserves execution continuity while eliminating fragmentation from streaming output.

### Conversion for LLM APIs

Before transmission to providers like OpenAI or Groq, [[`interpreter/core/llm/utils/convert_to_openai_messages.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/utils/convert_to_openai_messages.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/utils/convert_to_openai_messages.py) transforms the LMC format into provider-native schemas:

- **`type: code`** becomes OpenAI `function_call` payloads
- **`type: image`** converts to base64-encoded image URLs
- **`type: console`** with `format: output` renders as function results or standard messages depending on `function_calling` mode

### Conversation Storage

Fully formed LMC messages append to `interpreter.messages`, which serializes to JSON conversation files when history persistence is enabled. This storage maintains the complete execution context including code inputs and console outputs.

## Practical Implementation Examples

### Building Custom Language Emitters

Language implementations yield LMC-formatted chunks to integrate with the interpreter's streaming architecture. The E2B profile in [[`interpreter/terminal_interface/profiles/defaults/e2b.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/terminal_interface/profiles/defaults/e2b.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/terminal_interface/profiles/defaults/e2b.py) demonstrates this pattern:

```python
class MyLang:
    """A language that yields LMC-format chunks."""
    name = "mylang"

    def run(self, code):
        result = my_executor.run(code)
        yield {
            "type": "console",
            "format": "output",
            "content": result,
        }

```

### Programmatic Message Injection

Send structured messages directly into the conversation stack:

```python
interpreter = OpenInterpreter()
interpreter.chat(
    {"role": "user", "type": "message", "content": "List files in the current folder."},
    display=False,
)

```

The `chat` method validates and appends the dictionary to `interpreter.messages` without displaying intermediate output.

### Converting LMC to OpenAI Format

Transform existing message histories for external API calls:

```python
from interpreter.core.llm.utils import convert_to_openai_messages

openai_payload = convert_to_openai_messages(
    interpreter.messages, 
    function_calling=True, 
    vision=False, 
    interpreter=interpreter
)

```

This produces a list compatible with `openai.ChatCompletion.create` or equivalent endpoints.

## Key Source Files for LMC Handling

Understanding these files provides complete visibility into the LMC lifecycle:

| File | Purpose |
|------|---------|
| [`docs/protocols/lmc-messages.mdx`](https://github.com/openinterpreter/open-interpreter/blob/main/docs/protocols/lmc-messages.mdx) | Formal schema documentation and protocol specification |
| [[`interpreter/core/core.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/core.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/core.py) | Core message loop, chunk merging, and flag management via `_respond_and_store` |
| [[`interpreter/core/llm/utils/convert_to_openai_messages.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/utils/convert_to_openai_messages.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/utils/convert_to_openai_messages.py) | Provider-specific format translation logic |
| [[`interpreter/terminal_interface/profiles/defaults/e2b.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/terminal_interface/profiles/defaults/e2b.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/terminal_interface/profiles/defaults/e2b.py) | Reference implementation for custom language LMC emission |
| [[`interpreter/core/llm/llm.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/llm.py)](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/llm.py) | LLM provider wrapper expecting converted LMC messages |

## Summary

- **LMC messages** standardize Open Interpreter's internal communication using Python dictionaries with `role`, `type`, `content`, and optional `format` keys.
- The parsing pipeline in [`core.py`](https://github.com/openinterpreter/open-interpreter/blob/main/core.py) handles **chunk streaming, flag management, and message merging** to assemble complete conversation history.
- **Format conversion** in [`convert_to_openai_messages.py`](https://github.com/openinterpreter/open-interpreter/blob/main/convert_to_openai_messages.py) translates LMC structures to OpenAI-compatible function calls and image payloads.
- Custom languages integrate by **yielding LMC-formatted dictionaries** during code execution, as demonstrated in the E2B profile implementation.
- Complete protocol specifications reside in `docs/protocols/lmc-messages.mdx` within the openinterpreter/open-interpreter repository.

## Frequently Asked Questions

### What fields are required in an LMC message?

Every LMC message requires three fields: `role` (specifying the sender as `user`, `assistant`, or `computer`), `type` (defining the payload category such as `message`, `code`, or `console`), and `content` (containing the actual data payload). The `format` field is optional and provides additional context like `python` or `output` to sub-categorize the content.

### How does Open Interpreter handle streaming console output?

The interpreter receives console output as discrete chunks through the computer subsystem, then merges consecutive chunks sharing identical `role`, `type`, and `format` values into single LMC messages. The `_respond_and_store` method in [`interpreter/core/core.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/core.py) manages this merging while filtering ephemeral chunks like `active_line` markers through the `is_ephemeral` helper function.

### Can LMC messages be converted to standard OpenAI format?

Yes, the `convert_to_openai_messages` function in [`interpreter/core/llm/utils/convert_to_openai_messages.py`](https://github.com/openinterpreter/open-interpreter/blob/main/interpreter/core/llm/utils/convert_to_openai_messages.py) transforms LMC dictionaries into OpenAI-compatible structures. Code blocks become `function_call` objects, images convert to base64-encoded URLs, and console output renders as function results or standard messages depending on the `function_calling` parameter.

### Where is the LMC protocol formally documented?

The complete schema specification resides in [`docs/protocols/lmc-messages.mdx`](https://github.com/openinterpreter/open-interpreter/blob/main/docs/protocols/lmc-messages.mdx) within the openinterpreter/open-interpreter repository. This file defines valid values for all fields, provides examples, and documents the protocol's design rationale for maintaining structured communication between the user, language model, and execution environment.