Joshua hat eine eingebaute API: Deine Skripte, ein Roboter, eine Smart-Home-Zentrale oder jede App, die mit „OpenAI-compatible“-Servern funktioniert, können ihm eine Frage schicken und eine Antwort bekommen. Jede Anfrage führt den ganzen Joshua aus, mit Websuche, Werkzeugen und Gedächtnis, auf deinem Computer.
http://127.0.0.1:7861/v1.Joshua muss laufen, damit die API antwortet. Der Schlüssel ist in ~/AskJoshua/joshua/api.json gespeichert.
Liste im Terminal die Modelle auf, die du nutzen kannst, und stell dann eine Frage. Ersetze YOUR-KEY durch den Schlüssel aus dem Bereich.
curl http://127.0.0.1:7861/v1/models \ -H "Authorization: Bearer YOUR-KEY"
curl http://127.0.0.1:7861/v1/chat/completions \
-H "Authorization: Bearer YOUR-KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "joshua",
"messages": [{"role": "user", "content": "What is the weather in Turin today?"}]
}'Die Antwort kommt im Standardformat zurück; der Text steht in choices[0].message.content:
{
"id": "chatcmpl-5f2c9a01",
"object": "chat.completion",
"model": "qwen3-vl:8b-instruct",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Oggi è domenica, 8 novembre 2026."},
"finish_reason": "stop"
}]
}Joshua kann vor der Antwort im Web suchen, Seiten lesen oder Code ausführen, also kann eine Antwort ein paar Sekunden bis ein paar Minuten dauern, je nach Frage und Computer.
Am einfachsten ist die offizielle openai-Bibliothek: Richte sie auf Joshua statt auf OpenAI.
# pip install openai
from openai import OpenAI
joshua = OpenAI(base_url="http://127.0.0.1:7861/v1", api_key="YOUR-KEY")
reply = joshua.chat.completions.create(
model="joshua",
messages=[{"role": "user", "content": "Summarise today's main news in Italy in three lines."}],
)
print(reply.choices[0].message.content)Oder mit dem einfachen requests, zum Beispiel auf einem Raspberry-Pi-Roboter, der das Gespräch fortsetzt, indem er jedes Mal den Verlauf mitschickt:
# pip install requests
import requests
URL = "http://192.168.1.20:7861/v1/chat/completions" # your computer's address on the home network
KEY = "YOUR-KEY"
def ask_joshua(text, history=()):
messages = [*history, {"role": "user", "content": text}]
r = requests.post(URL, headers={"Authorization": f"Bearer {KEY}"},
json={"model": "joshua", "messages": messages}, timeout=600)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
print(ask_joshua("Which washing programme for a shirt marked 40 °C, gentle?"))const reply = await fetch("http://127.0.0.1:7861/v1/chat/completions", {
method: "POST",
headers: { "Authorization": "Bearer YOUR-KEY", "Content-Type": "application/json" },
body: JSON.stringify({
model: "joshua",
messages: [{ role: "user", content: "Write a haiku about Turin in the fog." }],
}),
}).then(r => r.json());
console.log(reply.choices[0].message.content);Eine Webseite auf einer anderen Website kann Joshua nicht direkt aufrufen; führe das in Node oder in deiner App aus.
Sende ein Foto als data:-URL in der Nachricht. Mit einem Modell, das Bilder sieht (qwen3-vl kann das), schaut Joshua es direkt an; sonst nutzt er sein lokales Bildwerkzeug.
import base64
from openai import OpenAI
joshua = OpenAI(base_url="http://127.0.0.1:7861/v1", api_key="YOUR-KEY")
photo = base64.b64encode(open("label.jpg", "rb").read()).decode()
reply = joshua.chat.completions.create(model="joshua", messages=[{
"role": "user",
"content": [
{"type": "text", "text": "What does this care label say?"},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{photo}"}},
],
}])
print(reply.choices[0].message.content)Du kannst Joshua mit einer system-Nachricht zusätzliche Anweisungen geben: Sie werden nach seinen eigenen angefügt. Und du kannst ihn bitten, den Austausch nicht als Chat zu speichern:
reply = joshua.chat.completions.create(
model="joshua",
messages=[
{"role": "system", "content": "You are the voice of a small robot. Answer in one short sentence, in Italian."},
{"role": "user", "content": "Che ore sono?"},
],
extra_body={"joshua_save": False}, # don't keep this exchange as a chat
)| Feld | Was es tut |
|---|---|
| model | joshua = dein lokales Standardmodell. Oder ein beliebiger Name aus /v1/models, wie qwen3-vl:8b-instruct. Cloud-Modelle (die auf cloud enden) werden nur genutzt, wenn du eines nennst. |
| messages | Das Gespräch: system-, user- und assistant-Nachrichten, die älteste zuerst. Joshua behält zwischen Anfragen nichts, also schick den Verlauf mit, an den er sich erinnern soll. |
| stream | true funktioniert mit Clients, die Streaming erwarten, aber die Antwort kommt am Ende auf einmal. |
| joshua_save | false = diesen Austausch nicht als 🔌-Chat speichern. Standard ist true. |
Standardmäßig können sich nur Programme auf demselben Computer verbinden. Um Joshua von einem Roboter, einem Telefon oder einem anderen Computer zu Hause zu nutzen:
~/AskJoshua/stop.sh aus, dann öffne Joshua wieder).http://192.168.1.20:7861/v1. Nutze diese Adresse auf dem anderen Gerät, mit demselben Schlüssel.Behalte es im Heimnetz. Öffne Port 7861 nicht an deinem Router: Der Schlüssel schützt Joshua, aber die Verbindung ist nicht verschlüsselt.
| Anfrage | Was es tut |
|---|---|
| GET /v1/models | Listet joshua und jedes installierte Modell auf, das Werkzeuge nutzen kann. owned_by sagt this computer oder cloud. |
| POST /v1/chat/completions | Führt Joshua mit den Nachrichten aus und gibt seine Antwort im OpenAI-Chatformat zurück. |
| Fehler | Bedeutung |
|---|---|
| 401 | Der Schlüssel fehlt oder ist falsch. Sende Authorization: Bearer YOUR-KEY. |
| 400 | Etwas an der Anfrage stimmt nicht, zum Beispiel ein unbekannter Modellname. Die Meldung sagt, was. |
| connection refused | Joshua läuft nicht, oder (von einem anderen Gerät) „Andere Geräte zulassen“ ist aus oder Joshua wurde nicht neu gestartet. |
Du brauchst nur das nackte Modell, ohne Joshuas Werkzeuge und Gedächtnis? Ollama hat eine eigene API unter http://127.0.0.1:11434, auch OpenAI-kompatibel unter /v1, ohne Schlüssel.
joshua_save: false.