Zum Inhalt springen

gRPC Interface

Alle Capabilities kommunizieren mit dem Selu-Orchestrator über einen einzigen gRPC-Service, der in capability.proto definiert ist. So bleibt die Schnittstelle einheitlich, unabhängig davon, in welcher Sprache deine Capability geschrieben ist.

capability.proto
syntax = "proto3";
package selu.capability.v1;
service CapabilityService {
// Invoke a tool within this capability.
rpc Invoke(InvokeRequest) returns (InvokeResponse);
// Health check (optional, used by orchestrator for readiness).
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
}
message InvokeRequest {
// Name of the tool to invoke (matches manifest.yaml tools[*].name).
string tool_name = 1;
// JSON-encoded parameters from the LLM's tool call.
string parameters = 2;
// Opaque session context passed by the orchestrator.
map<string, string> context = 3;
}
message InvokeResponse {
// JSON-encoded result returned to the LLM.
string result = 1;
// Indicates whether the invocation succeeded.
bool success = 2;
// Human-readable error message (only set when success is false).
string error = 3;
}
message HealthCheckRequest {}
message HealthCheckResponse {
bool healthy = 1;
}
FeldTypBeschreibung
tool_namestringEntspricht dem Feld name in der Tool-Liste deines manifest.yaml. Eine Capability kann mehrere Tools bereitstellen.
parametersstringJSON-Objekt mit den Parametern aus dem Tool-Call des LLM. Dieses Feld musst du in deinem Handler parsen.
contextmap<string, string>Metadaten vom Orchestrator, darunter session_id, user_id und weiterer benutzerdefinierter Kontext. Verlass dich nicht auf bestimmte Schlüssel. Behandle das Feld als optional.
FeldTypBeschreibung
resultstringJSON-kodiertes Ergebnis. Dieses wird als Tool-Ergebnis in das LLM-Gespräch eingefügt.
successbooltrue, wenn das Tool erfolgreich ausgeführt wurde
errorstringFehlermeldung, die dem LLM angezeigt wird, wenn success false ist. Das LLM kann damit den Fehler dem Nutzer erklären.

Dein gRPC-Server muss im Container auf Port 50051 lauschen. Der Orchestrator verbindet sich automatisch mit diesem Port.

Hier ist ein minimales Python-Beispiel:

server.py
import grpc
from concurrent import futures
import json
import capability_pb2 as pb2
import capability_pb2_grpc as pb2_grpc
class CapabilityServicer(pb2_grpc.CapabilityServiceServicer):
def Invoke(self, request, context):
params = json.loads(request.parameters)
if request.tool_name == "weather_lookup":
location = params.get("location", "unknown")
# ... call weather API ...
return pb2.InvokeResponse(
result=json.dumps({"temperature": 22, "conditions": "sunny"}),
success=True,
)
return pb2.InvokeResponse(
success=False,
error=f"Unknown tool: {request.tool_name}",
)
def HealthCheck(self, request, context):
return pb2.HealthCheckResponse(healthy=True)
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
pb2_grpc.add_CapabilityServiceServicer_to_server(CapabilityServicer(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
if __name__ == "__main__":
serve()

Erzeuge Stubs aus capability.proto mit den üblichen gRPC-Tools für deine Sprache. Selu veröffentlicht die Proto-Datei unter:

https://github.com/selu-bot/proto/blob/main/capability/v1/capability.proto