Use Gyblos from your code
Run the local buyer and point OpenAI or Anthropic clients at it to chat with a Gyblos seller.
The buyer is a small server on your own computer, at http://127.0.0.1:4031. It speaks the OpenAI and
Anthropic APIs, so programs written for those services can use a Gyblos seller by changing their base URL.
For each request it gets a signed free quote from the seller and streams the answer back over a direct
peer-to-peer connection.
What works today
| Feature | Beta status |
|---|---|
| Whole conversations: system message, history, new message | Yes, up to 1024 messages |
OpenAI POST /v1/chat/completions and Anthropic POST /v1/messages | Yes, whole answers and streaming |
GET /v1/models | Yes, the model your buyer asks for |
| Free offers | Yes |
| Tools (function calling), both formats, whole answers and streaming | Yes, see Tools |
| Claude Code | Only with a seller on a larger model |
| Cursor agent mode | No: it calls from Cursor's cloud |
| Images, structured output, several answers | Not yet: refused with a clear 400 error |
| Paid offers | Outside this guide |
A seller serves each buyer up to 30 answers per minute by default. An answer is at most 4096
tokens unless you raise the buyer's limit (up to 32768); a longer request is served up to that limit and
ends with finish reason length.
Your prompt reaches the seller you configured, whose machine runs the model and can read it. Do not send passwords, keys or other secrets.
Before you start
- An invitation with a private relay token.
- The NodeId and owner wallet of the seller you will use, from a source you trust (the seller
prints both with
gyblos doctor). The seller must be registered; the buyer checks its identity on Solana devnet. - Git, Node.js 24.22.1 or later, and pnpm 10 (
corepack enableprovides it).
In the beta the buyer runs from the source repository; the installer and the npm package contain the seller only.
Install and configure
git clone https://github.com/Gyblos/gyblos-node.git
cd gyblos-node
pnpm install --frozen-lockfile
pnpm buyer:initbuyer:init asks for the seller's NodeId and owner wallet, shows the settings (model qwen3-0.6b,
answers up to 4096 tokens, free quotes only) and saves them after you confirm. It sends nothing to the
seller or the chain. pnpm buyer:init --advanced also sets the model, the answer limit and the endpoints.
Start the buyer
Type the relay token without showing it, then start the buyer in the same terminal:
read -rs GYBLOS_RELAY_TOKEN && export GYBLOS_RELAY_TOKEN
pnpm buyer:freeLeave it running. In another terminal, check that it answers:
curl http://127.0.0.1:4031/v1/modelsThe list names the one model your buyer asks for; use that name as model in your requests. For a quick
conversation in the terminal instead, run pnpm buyer:chat, which starts its own buyer.
Send a conversation
curl http://127.0.0.1:4031/v1/chat/completions \
-H 'content-type: application/json' \
-d '{
"model": "qwen3-0.6b",
"messages": [
{"role": "system", "content": "Answer in one short sentence."},
{"role": "user", "content": "My name is Ana."},
{"role": "assistant", "content": "Nice to meet you, Ana!"},
{"role": "user", "content": "What is my name?"}
]
}'OpenAI SDK
Use base URL http://127.0.0.1:4031/v1. The free buyer does not check the API key, but the SDK needs a
non-empty one.
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'http://127.0.0.1:4031/v1',
apiKey: 'local',
});
const stream = await client.chat.completions.create({
model: 'qwen3-0.6b',
stream: true,
messages: [
{ role: 'system', content: 'Be brief.' },
{ role: 'user', content: 'My dog is called Rocky.' },
{ role: 'assistant', content: 'Got it: your dog is Rocky.' },
{ role: 'user', content: "What is my dog's name?" },
],
});
for await (const chunk of stream)
process.stdout.write(chunk.choices[0]?.delta?.content ?? '');Anthropic SDK
Use base URL http://127.0.0.1:4031 (without /v1). max_tokens is required, as with Anthropic.
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
baseURL: 'http://127.0.0.1:4031',
apiKey: 'local',
});
const message = await client.messages.create({
model: 'qwen3-0.6b',
max_tokens: 200,
system: 'Be brief.',
messages: [
{ role: 'user', content: 'My dog is called Rocky.' },
{ role: 'assistant', content: 'Got it: your dog is Rocky.' },
{ role: 'user', content: "What is my dog's name?" },
],
});
console.log(message.content[0].text);Tools
Send tools as each API defines them. When the model wants a tool, the answer ends with
finish_reason: "tool_calls" (Anthropic: stop_reason: "tool_use") and carries the call. Your program
runs the tool and sends the result back in the next request, with the whole conversation:
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'http://127.0.0.1:4031/v1',
apiKey: 'local',
});
const tools = [
{
type: 'function',
function: {
name: 'get_time',
description: 'Current local time in a city',
parameters: {
type: 'object',
properties: { city: { type: 'string' } },
required: ['city'],
},
},
},
];
const messages = [
{ role: 'user', content: 'What time is it in Santiago? Use the tool.' },
];
const first = await client.chat.completions.create({
model: 'qwen3-0.6b',
messages,
tools,
});
const call = first.choices[0].message.tool_calls[0];
// Run the tool yourself, then send its result back.
messages.push(first.choices[0].message, {
role: 'tool',
tool_call_id: call.id,
content: '15:42',
});
const second = await client.chat.completions.create({
model: 'qwen3-0.6b',
messages,
tools,
});
console.log(second.choices[0].message.content);With the Anthropic SDK, send tools with input_schema, read the tool_use blocks and answer with
tool_result blocks, as with Anthropic. The buyer asks only sellers that serve tools; if none does, it
answers 503 and says so.
The default model, qwen3:0.6b, handles simple calls like this one. Agents that send many tools and long instructions, such as Claude Code, need a seller on a larger model through the OpenAI or Anthropic engine.
Options and errors
Options that clients send by default and that do not change the answer are accepted and ignored, such as
temperature, top_p, user, metadata, stream_options and, in the Anthropic format, thinking
(thinking is always off). Options that would change it are refused unless they hold their neutral value:
response_format (text), n (1), stop and stop_sequences, and logprobs. Images are always
refused.
| Answer | Meaning |
|---|---|
| 400 | The request uses something not supported yet; the message and param name it. |
| 503 | No seller is available right now. With Retry-After, the seller failed recently or hit its per-minute limit: the OpenAI and Anthropic SDKs wait and retry on their own. |
| 504 | The seller did not answer in time. |
Errors use each API's own shape, so SDKs raise their usual exceptions.