Overview

Tinkuy agents are stateless by default. For persistent conversations and real-time interaction, you can wrap your agent in a Cloudflare Durable Object (DO).

Basic DO Agent

import { Agent, defineTool } from '@carloscortezcloud/tinkuy-agent';
import { StyrRouter } from '@carloscortezcloud/styrr-llm';

export class ChatAgent extends DurableObject {
  private agent: Agent;
  private messages: Message[] = [];

  constructor(ctx: DurableObjectState, env: Env) {
    super(ctx, env);

    this.agent = new Agent({
      router: new StyrRouter({
        apiKey: env.OPENROUTER_API_KEY,
        models: [{ id: 'nvidia/nemotron-3-ultra:free' }],
      }),
      tools: [/* ... */],
      systemPrompt: 'You are a helpful assistant.',
    });
  }

  async handleMessage(userMessage: string) {
    this.messages.push({ role: 'user', content: userMessage });
    const result = await this.agent.run(this.messages);
    this.messages.push({ role: 'assistant', content: result.text });
    return result;
  }
}

WebSocket Agent

export class WebSocketAgent extends DurableObject {
  async fetch(request: Request) {
    const pair = new WebSocketPair();
    const [client, server] = Object.values(pair);

    this.ctx.acceptWebSocket(server);

    server.addEventListener('message', async (event) => {
      const result = await this.agent.run(event.data);
      server.send(JSON.stringify(result));
    });

    return new Response(null, { status: 101, webSocket: client });
  }
}

wrangler.toml

[durable_objects]
bindings = [
  { name = "CHAT_AGENT", class_name = "ChatAgent" }
]

[[migrations]]
tag = "v1"
new_classes = ["ChatAgent"]

Roadmap

  • v0.2: Streaming support (released)
  • v0.3: Conversation persistence with auto-summarization
  • v0.4: Multi-agent orchestration (Tinkuy Agent → sub-agents)
  • v0.5: WebSocket-native agent loop (DO + real-time)