Skip to main content

Run LiveKit agents in text-only, stateless mode for SMS and chat

Project description

LiveTxt: Run LiveKit Agents with SMS, Chat, and API Channels

Run your existing LiveKit agents across any text channel (like SMS, chat, or API) without modifying your agent code. LiveTxt extends LiveKit's real-time voice and video capabilities to text, enabling channel-agnostic AI agents for SMS and other messaging platforms. Enjoy drop-in compatibility with livekit-agents.

  • Channel-agnostic by design (voice/video via LiveKit, text/API via LiveTxt)
  • Drop-in compatibility with livekit-agents (no agent rewrites)
  • Stateless text execution (each turn in → result out)

Aim and vision

A single agents/multi-agent system API (livekit-agents) that runs on any channel.

  • One codebase → many channels
  • Works for single agents and coordinating multi-agent entrypoints
  • LiveKit handles real-time voice/video; LiveTxt handles chat, SMS, and API
  • Keep agent code identical; switch runtimes by channel

Channels

  • Voice/Video: LiveKit room runtime
  • Chat/SMS/API: LiveTxt execute_job()

Install

pip install -e .
# or with dev tools
pip install -e ".[dev]"

Quick start: HTTP Worker

The easiest way to run an agent is with the built-in HTTP server that auto-loads your agent:

# Start worker (agent auto-loads on startup)
python -m livetxt.cli serve examples/weather-agent/weather_agent.py --port 8081

# Agent is ready to receive requests - no manual loading needed!

Then send requests from the gateway or directly:

curl -X POST http://localhost:8081/execute \
  -H "Content-Type: application/json" \
  -d '{
    "request_id": "req_1",
    "session_id": "session_1",
    "user_id": "user_1",
    "message": "What's the weather?"
  }'

Quick start: Programmatic

Define your agent exactly as you do for livekit-agents, then execute it with a user message.

from livetxt import execute_job, JobRequest, SerializableSessionState
from livekit.agents import JobContext

async def my_agent(ctx: JobContext):
    await ctx.connect()

    @ctx.room.on("data_received")
    def handle_message(data: bytes, topic: str, participant):
        msg = data.decode("utf-8")
        ctx.room.local_participant.publish_data(
            f"You said: {msg}".encode("utf-8"),
            topic="lk.chat",
        )

request = JobRequest(
    job_id="conversation_123",
    user_input="Hello!",
    state=SerializableSessionState(),
)

result = await execute_job(my_agent, request)
print(result.response_text)  # You said: Hello!

Multi‑turn

Pass the previous turn's state into the next request.

# turn 1
r1 = JobRequest(job_id="t1", user_input="My name is Alice", state=SerializableSessionState())
res1 = await execute_job(my_agent, r1)

# turn 2
r2 = JobRequest(job_id="t2", user_input="What's my name?", state=res1.updated_state)
res2 = await execute_job(my_agent, r2)

How it works (brief)

  • execute_job() creates a text‑only JobContext with a fake Room and Participant.
  • Your agent registers handlers (e.g., data_received).
  • The user message is injected after handlers are registered.
  • When your agent calls publish_data(), the text is captured and returned as a JobResult.

What works today

  • Single-agent and multi-agent entrypoints (multiple handlers/agents)
  • Text agents using ctx.room.on("data_received")
  • Multi‑turn conversations via SerializableSessionState

Not yet:

  • Agents built on AgentSession + LLM
  • Function/tool calling
  • Audio/video (handled by LiveKit runtime)

Examples

See examples/ for runnable agents. A good place to start:

  • examples/weather-agent/

Each example folder includes its own README with run instructions.

Testing

# run all tests
pytest tests/ -v

# with coverage
pytest --cov=livetxt --cov-report=term tests/

Troubleshooting

  • No response? Ensure your handler listens to data_received and you call await ctx.connect() before relying on events.
  • Byte/str issues? Encode/decode UTF‑8 around publish_data() and handler inputs.
  • State not sticking? Always pass result.updated_state into the next JobRequest.

Development

Contributions are welcome! To set up for development:

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run linting
ruff check --fix livetxt/
black livetxt/
mypy livetxt/

See tests/README.md for testing guidelines and WARP.md for architecture notes.

License

Apache‑2.0. See LICENSE and NOTICE.

Related

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

livetxt-0.0.2.tar.gz (50.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

livetxt-0.0.2-py3-none-any.whl (45.3 kB view details)

Uploaded Python 3

File details

Details for the file livetxt-0.0.2.tar.gz.

File metadata

  • Download URL: livetxt-0.0.2.tar.gz
  • Upload date:
  • Size: 50.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.23

File hashes

Hashes for livetxt-0.0.2.tar.gz
Algorithm Hash digest
SHA256 93e5f78bd88610ba3e6a3c9f03a8dd46048b8411e38e10bc7a1b71bca5776f04
MD5 2ee3e2f22265532ffe6d7ff5189097f7
BLAKE2b-256 7a0e0e39852f4de3b646270a335d94ce59d48d76226eec701b2cd4b8ccfa05f2

See more details on using hashes here.

File details

Details for the file livetxt-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: livetxt-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 45.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.23

File hashes

Hashes for livetxt-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1398b27328e7663873d05dc96c8a0029ca15771fabb8a611a938ebf6e20cc2bf
MD5 7df6d62f209fe8b5586b2f56203a4a4b
BLAKE2b-256 3fae3f236c0d098c20ae4dfc3d9a2bb010dc980b2d224f0adbd3c5a201b2ce5a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page