Skip to main content

TWYLT 1.0.0

TWYLT — TWYLT Wraps Your Local Tool.

TWYLT is a small, language-independent protocol for turning ordinary executables into self-describing JSON tools. This repository contains the Python reference implementation.

A TWYLT tool can publish its identity, requirements, input/output JSON Schemas and examples, then accept validated JSON input and return validated JSON output. The protocol does not depend on ToolHub, MCP, an LLM, or any particular agent framework.

Python package: twylt 1.0.0
TWYLT protocol: 1.8

Quick start

Install the package:

pip install twylt

Define a tool:

from pydantic import BaseModel, Field
from twylt import Tool


class Input(BaseModel):
    text: str = Field(..., description="Text to repeat")


class Output(BaseModel):
    text: str = Field(..., description="Repeated text")


class Echo(Tool[Input, Output]):
    input_model = Input
    output_model = Output

    name = "echo"
    version = "1.0.0"
    description = "Return the supplied text."

    def biz(self, data: Input) -> Output:
        return Output(text=data.text)


if __name__ == "__main__":
    Echo.run()

Run it with JSON:

python echo.py '{"text":"hello"}'
{"text":"hello"}

Ask the executable to describe itself:

python echo.py '{"describe":"json_spec"}'

The response includes the tool identity, requirements, inputSchema, outputSchema, examples, and the TWYLT protocol version.

The contract

A Python tool subclasses Tool, declares Pydantic input_model and output_model, supplies metadata, and implements biz(). TWYLT handles the protocol around that business logic: discovery, transports, validation, schema publication and normalized errors.

The complete language-independent protocol is specified in TWYLT.md. The Python API is the reference implementation, not the definition of the protocol.

Self-description

TWYLT supports five describe modes:

Mode Result
brief Short human-readable tool description
schema inputSchema and outputSchema
requirements Dependency installation metadata
few_shots Example input/output pairs
json_spec Complete machine-readable tool description

Description can be requested through JSON:

python tool.py '{"describe":"schema"}'
python tool.py '{"describe":"requirements"}'
python tool.py '{"describe":"json_spec"}'

For compatibility with executable discovery, INPUT_DESCRIBE is also supported:

INPUT_DESCRIBE=json_spec python tool.py

A non-empty describe request is processed before business-input validation and never calls biz().

Input and output

For normal execution, input is selected in this order:

  1. first positional CLI JSON object;
  2. non-empty JSON from stdin;
  3. input.json.

CLI and stdin execution return JSON on stdout. File-mode execution writes output.json.

python tool.py '{"path":"."}'
printf '%s' '{"path":"."}' | python tool.py

Object contracts are strict recursively: undeclared fields are rejected on both input and output. Published JSON Schemas reflect the same behavior with additionalProperties: false.

Schema identity

Input and output contracts may be versioned independently from both the tool and the TWYLT protocol:

class MyTool(Tool[Input, Output]):
    input_schema_name = "MyToolInput"
    input_schema_version = "1.0.0"
    output_schema_name = "MyToolOutput"
    output_schema_version = "1.0.0"

These become JSON Schema $id and x-schema-version. Pydantic field metadata such as descriptions, aliases, constraints, defaults and JSON Schema extras is preserved in the published schemas.

Errors and exit codes

Errors are written to stderr; stdout remains reserved for successful JSON results. JSON is the default error representation.

{
  "error": {
    "type": "validation_error",
    "source": "twylt",
    "stage": "input",
    "message": "Input validation failed",
    "errors": []
  }
}

source: "twylt" identifies protocol/framework failures; source: "tool" identifies failures from business logic. Stages are transport, describe, input, biz, and output.

Exit code Meaning
0 success
2 input validation failure
3 output validation failure
4 transport/protocol/describe failure
5 business execution failure

Use --error-format human for human/native diagnostics. --debug adds traceback information; the environment equivalents are TWYLT_ERROR_FORMAT and TWYLT_DEBUG.

Service CLI

Every tool also exposes service options before normal transport processing:

python tool.py --help
python tool.py --version
python tool.py -v

--version prints the tool name and version; -v prints only its version.

Dependency-independent discovery

A launcher can inspect static metadata before importing the complete tool module:

from pathlib import Path
from twylt.bootstrap import run_tool_file

run_tool_file(Path(__file__).with_name("tool.py"))

This allows requirements discovery even when optional runtime dependencies of the tool are not installed. If full loading for json_spec fails because such a dependency is unavailable, statically discoverable metadata is still returned and unavailable schemas are represented as {}.

See examples/list_directory for a complete example.

Relationship to MCP and ToolHub

TWYLT is deliberately independent of both. ToolHub is one possible consumer. An MCP adapter can mechanically map name, description, inputSchema, and outputSchema to MCP Tool fields and map executable invocation to tools/call, without making MCP part of the TWYLT runtime contract.

Development

Create an environment and run the cumulative regression suite:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip build
python -m pip install -e '.[test]'
python -m pytest -q

Build the distributions:

python -m build

Before a release, both the source tree and the final packaged artifact must pass the complete cumulative test suite. scripts/verify_package.py additionally verifies package installation and version metadata.

Project documentation

TWYLT 1.0.0 succeeds ToolSpec 1.6.2. The first protocol version under the TWYLT name is 1.8; historical names remain in the changelog and ADRs intentionally.

License

MIT. See LICENSE.

Release files for twylt 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for twylt 1.0.0
File Interpreter ABI Platform
twylt-1.0.0-py3-none-any.whl Python 3 none any Details

Release files / twylt-1.0.0-py3-none-any.whl

Download URL twylt-1.0.0-py3-none-any.whl
Size 12.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9c06a769ef733f95f59e76310256bc3a68aa409183dcc6ad309dc9f0c1523eb5
BLAKE2b-256 checksum
How to use checksums
42967996a4dcb43d19074f7a84814e308df9f5b2a52a29ac34899998b2df8974
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

1.0.0 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page