Crystal Lattice
Open Source

For people who outgrow
one-size-fits-all agents.

Crystal Lattice is a model-native agent platform: the harness changes around the model, including its system message, tool schema, request behavior, provider-native state, and UI controls. Built-in plugins provide Codex, Claude, Gemini, Qwen, Kimi, and Grok-style defaults, and your config can replace them.

Terminal

$
curl -fsSL https://download.crystallattice.dev/crystal-lattice-cli/install.sh | bash

macOS Intel or Apple silicon · Linux x64 or ARM64

Installation guide

Built-in model-family harnesses

Codex-style toolsClaude-style workflowsGemini-oriented toolsQwen-oriented toolsKimi-oriented toolsGrok-oriented tools

Computer to phone

Start at your desk. Keep going from your phone.

Start Crystal Lattice in the project folder where you want the agent to work. The terminal UI can stay open, but the work is not trapped there: the app UIs can open the same sessions and watch responses stream.

On the same Wi-Fi, Crystal Lattice Control can find your computer automatically. Choose Automatic Discovery, select your computer, and continue the same workspace from your phone.

Automatic discovery uses the local network. If your phone is outside that network, use the bridge section below.

Run the local workspace

01

Install the CLI

Choose the installation method for your platform above, then verify that the command is available.

Choose an installation method
bash — 80×24
$ crystal-lattice --help
02

Start Crystal Lattice with local discovery

bash — 80×24
mkdir -p ~/crystal-lattice-demo
cd ~/crystal-lattice-demo
crystal-lattice \
--server \
--console \
--config-local \
--host 0.0.0.0 \
--port 9000 \
--enable-bonjour
03

Open the mobile app

Open Crystal Lattice Control, choose Automatic Discovery, and select your computer.

Outside your local network

Pair through a self-hosted bridge

Hosted bridge service is coming soon. Today, when your phone is not on the same network as your computer, deploy your own bridge and pair through it.

The bridge gives Crystal Lattice clients a way to reconnect from outside the local network. Local bridge hosting is useful for development and testing, but production use should deploy the bridge somewhere reachable.

Deploy the bridge on AWS

01

Create the bridge deployment

bash — 80×24
ALLOW_AWS_DEPLOY=1 deploy/aws-ec2/build.sh \
--profile secure \
--stack-name crystal-lattice-bridge \
--region us-east-1
ALLOW_AWS_DEPLOY=1 deploy/aws-ec2/up.sh \
--profile secure \
--stack-name crystal-lattice-bridge \
--region us-east-1
02

Start Crystal Lattice with the bridge URL

bash — 80×24
crystal-lattice \
--server \
--console \
--config-local \
--host 0.0.0.0 \
--port 9000 \
--bridge-url wss://<your-cloudfront-domain>/ws/websocket
03

Pair from the phone

Open Crystal Lattice Control, choose Bridge Service, enter the bridge URL, select your computer, and enter the pairing code.

Model-native harnesses

Stop forcing every model through the same prompt and tools.

Model-native means Crystal Lattice changes the harness around the model: system message, tool schema, request behavior, provider-native state, and UI controls. The built-in defaults do this with plugins, and those plugins can be replaced.

Model familyBuilt-in harnessWhat changes
Codex / GPT coding modelscodex-toolsCodex-style shell tools, apply patch semantics, skills block, model-family system instructions.
Claudeclaude-toolsClaude-oriented tool schema and workflow conventions.
Geminigemini-tools + compaction pluginsGemini-oriented system message and tool behavior, optional compaction flow.
Qwenqwen-toolsQwen-oriented tool and instruction style.
Kimikimi-toolsKimi-oriented tools and prompt behavior.
Grokgrok-toolsGrok-oriented tools and request behavior.
OpenAI Responsesopenai_responsesResponses-native reasoning, usage/cost metadata, attachments, prompt caching, native compaction.
OpenRouteropenrouterOpenRouter model routing, reasoning/web/image extensions depending on provider path.

Native provider features

Provider-specific behavior can become real UI.

Some capabilities are not generic chat settings. Reasoning effort, verbosity, usage, token counts, cache information, duration, and cost metadata depend on the provider path.

Crystal Lattice lets provider and feature plugins expose those controls and outputs directly to the UI, so native behavior is visible instead of hidden behind a generic wrapper.

Session settings with magnified medium reasoning effort and medium verbosity controls.

Reasoning and verbosity

Expose model-specific controls when the provider supports them.

A completed coding-plan response with magnified input, estimated cached, completion, reasoning-token, and estimated-cost metadata.

Usage and cost transparency

Surface token, cache, duration, and cost metadata when the provider supplies it.

Everything is replaceable

Serious users eventually disagree with the harness.

Crystal Lattice treats that as normal. Providers, provider extensions, features, tools, application actions, session behavior, and UI elements are all plugin surfaces.

The built-in plugins give you useful defaults. Your own plugins can replace the parts your workflow disagrees with, and config can point at those plugins without waiting for upstream approval.

Code examples are illustrative placeholders, not final API.

Provider

Add native support for a model API.

python
# Placeholder example, not final API.
class MyProvider:
    name = "my_provider"

    def to_native_messages(self, messages, state, *, context=None):
        return convert_to_my_api(messages)

    def stream_api(self, native_messages, state):
        yield from call_my_model(native_messages, state)

Provider extension

Surface provider metadata, reasoning, citations, or UI fields.

python
# Placeholder example, not final API.
class UsageFooter:
    name = "usage_footer"

    def finalize(self, final_messages, native_messages, state):
        return add_usage_metadata(final_messages, state)

    def get_ui_elements(self, config, context=None):
        return [
            {"ui_type": "message_footer", "data": "metadata.total_cost"}
        ]

Feature

Transform context, request behavior, or final messages.

python
# Placeholder example, not final API.
class ProjectContext:
    name = "project_context"

    def to_native_messages(self, messages, native_messages, state):
        return inject_project_context(native_messages)

Tool

Expose Python, Node, Bash, or MCP-backed capabilities.

python
# Placeholder example, not final API.
class SearchTickets:
    name = "search_tickets"

    def get_tool_schemas(self, state):
        return [ticket_search_schema]

    def execute_tool(self, tool_name, payload, state):
        return search_linear_or_jira(payload)

Application plugin

Add session-level workflow actions.

python
# Placeholder example, not final API.
class CreateReleaseNotes:
    name = "release_notes"

    def get_actions(self, state):
        return [
            {
                "id": "release_notes.create",
                "label": "Create release notes",
            }
        ]

    def execute_action(self, app, action_id, params, context, state):
        return create_release_notes(app, params)

UI schema

Render settings and actions in app UIs without hardcoding them.

python
# Placeholder example, not final API.
def get_ui_elements(self, config, context=None):
    return [
        {
            "ui_type": "session_action",
            "label": "Sync down",
            "action_id": "cloud.sync_down",
        },
        {
            "type": "select",
            "key": "reasoning_effort",
            "label": "Reasoning effort",
        },
    ]

Session workbench

Treat sessions as workspaces, not disposable chats.

Agent work is more than a transcript. Built-in session plugins add reusable actions, checkpoints, settings, and other controls to the session workflow.

The workbench is plugin-driven too: built-in plugins provide the default behavior, and your own plugins can add or replace workflow actions.

Session actions menu showing plugin-provided copy, title, deletion, summarization, and native compaction controls alongside session settings.

Chat actions

Message and session actions exposed by plugins.

Snapshots dialog showing automatic pre-compaction and pre-deletion recovery points with Select, Restore, and Delete controls.

Snapshots

Create, inspect, select, and restore session checkpoints.

Session settings showing OpenAI model, reasoning, verbosity, prompt cache, web search, and compaction transcript controls contributed by plugins.

Settings and plugins

Per-session controls from plugin UI schema.

Plugin authoring

Ask an agent to plan the plugin.

A user-owned plugin workflow still needs product polish, but the design goal is straightforward: inspect the docs, pick the right plugin type, copy the closest template, write tests, and load the plugin from config.

prompt
I want to build a Crystal Lattice plugin.

Please inspect the plugin documentation in this repository, especially:
- plugins/docs/index.md
- plugins/docs/tool-plugins.md
- plugins/docs/application-plugins.md
- plugins/docs/provider-plugins.md
- plugins/docs/provider-extensions.md
- plugins/docs/feature-plugins.md
- plugins/docs/ui-elements.md
- plugins/docs/plugin-packaging-and-loading.md

Goal:
Create a plugin that [describe what I want].

Please:
1. Identify whether this should be a provider, provider extension, feature, tool, or application plugin.
2. Find the closest existing plugin or template to copy from.
3. Explain what UI, if any, the plugin should expose.
4. Propose the file layout.
5. Draft an implementation plan.
6. Tell me what tests should be added before coding.
json
{
  "plugins": [
    "path:./plugins/my-custom-plugin"
  ]
}

Python SDK

Automate the same harness with Python.

When the work becomes repetitive, use the same configured agents and plugins from Python. The example below sketches a short sales-letter workflow over a CSV of leads.

The final webpage should verify this against the current SDK and may add a small helper if the public API needs a simpler "run until final" path.

sdk-api-needs-verification
python
import pandas as pd
from agent_app import AgentApplication

app = AgentApplication.from_config("./.crystal/config.json")
leads = pd.read_csv("leads.csv")

def draft(row):
    session = app.create_session(agent_id="codex-openrouter")
    app.add_message(
        session.session_id,
        "user",
        f"""
        Write a concise first sales email.

        Name: {row.name}
        Role: {row.role}
        Company: {row.company}
        Notes: {row.notes}
        """,
    )
    result = app.run_until_final(session.session_id)
    return result.content

leads["draft"] = leads.apply(draft, axis=1)
leads.to_csv("drafts.csv", index=False)

Use the harness you can inspect and replace.

Start with built-in model-family plugins, run Crystal Lattice on your computer, continue from phone or app UI, and replace the parts of the harness your workflow disagrees with.