Use the gRPC API from any language
This guide connects an app written in any language to a Priompt server through its gRPC API. The API is one service, priompt.v1.PromptService, defined in a single file, prompt.proto. It covers every operation, including history, branches, merges, and rollback, which the Python and Node SDKs don't all wrap.
Prerequisites
Before you begin, make sure you have:
-
A running server: see the Quickstart. The examples use
localhost:8443without authentication. -
The contract: clone the proto repository, which holds
proto/priompt/v1/prompt.proto:git clone https://github.com/priompt/proto -
grpcurl: to try calls from a shell.
-
buf: to generate a client. Not needed for Go.
Call the API with grpcurl
The server doesn't enable gRPC reflection, so pass the .proto file to grpcurl.
To fetch a prompt, run from the directory that holds the proto clone:
grpcurl -plaintext -H "authorization: Bearer <token>" \
-import-path proto/proto -proto priompt/v1/prompt.proto \
-d '{"uri":"priompt://acme/onboarding/welcome"}' \
localhost:8443 priompt.v1.PromptService/GetPrompt
{
"uri": "priompt://acme/onboarding/welcome",
"template": "Hi {name}, welcome to {org}!\n",
"slots": [
"name",
"org"
],
"versionHash": "22e5cc10ac0f3d70fd97c6b554a36abcb3173731412212dc222106e9cbcac402"
}
Replace <token> with a token the server accepts, or drop the -H line for a server without authentication. grpcurl prints field names in camel case, such as versionHash. Generated code uses each language's own convention.
Generate a client
To generate a client with buf:
-
Next to the
protoclone, create abuf.gen.yamlthat names your language's plugins. This one generates Go:buf.gen.yamlversion: v2inputs:- directory: proto/protoplugins:- remote: buf.build/protocolbuffers/goout: genopt: paths=source_relative- remote: buf.build/grpc/goout: genopt: paths=source_relativeFor another language, swap in its plugins from the Buf Schema Registry, for example
buf.build/grpc/javaorbuf.build/grpc/csharp. Remote plugins run on Buf's servers, so you don't installprotocor any plugin locally. -
Generate the code:
buf generatefind gen -type fOutputgen/priompt/v1/prompt.pb.gogen/priompt/v1/prompt_grpc.pb.go
Use the published Go stubs
Go apps can skip generation. The proto module publishes its generated stubs:
go get github.com/priompt/[email protected]
package main
import (
"context"
"fmt"
"log"
priomptv1 "github.com/priompt/proto/gen/priompt/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/metadata"
)
func main() {
conn, err := grpc.NewClient("localhost:8443", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client := priomptv1.NewPromptServiceClient(conn)
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <token>")
p, err := client.GetPrompt(ctx, &priomptv1.GetPromptRequest{Uri: "priompt://acme/onboarding/welcome"})
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s%s\n", p.GetTemplate(), p.GetVersionHash()[:12])
}
Hi {name}, welcome to {org}!
22e5cc10ac0f
Follow the connection rules
Every client, generated or not, talks to the server the same way:
- Address:
host:8443. The connection is plaintext unless the server runs with-tls-certand-tls-key. A server with-client-caalso requires a client certificate signed by that CA. - Authentication: send the metadata header
authorization: Bearer <token>on every call. A server without tokens ignores it. - Pinning: set
refonGetPromptRequestto a branch name or a full 64-character commit hash. The response then carriescommit_hash. - Errors: failures use standard gRPC status codes. A missing prompt returns
NotFoundwith the messageprompt "<uri>" not found. See Errors.
The gRPC API reference documents every RPC and message.
Subscribe without an SDK
The server publishes a change event on its NATS broker each time the served version of a prompt changes. To receive events from any language, connect a NATS client to nats://127.0.0.1:4222, or nats://<api-token>@host:4222 with your API token when the broker requires one. Then subscribe to the prompt's subject. An org-scoped token can subscribe only inside its org.
The subject is priompt. followed by the address's segments joined by .. Inside a segment, every byte other than a letter, a digit, _, or - is percent-encoded as % and two uppercase hex digits. For example, priompt://acme/support/agent publishes on priompt.acme.support.agent, priompt://acme.corp/x/a.b on priompt.acme%2Ecorp.x.a%2Eb, and priompt.acme.> matches every prompt in the acme org. Servers before v0.7.3 didn't encode segments.
The message body is JSON:
{"version":"bd45a4721079b550b784f3fe346b34a86d640ebd6e9b0248ea5b957aea345274","classification":"minor edit"}
version is the new version hash, and classification is the semantic verdict. The server omits classification when it couldn't classify the change. Treat an event as a signal to fetch the prompt again over gRPC. To decide which verdicts your app reloads on its own, see Hot-reload prompts safely.
Next steps
- gRPC API: every RPC, message, and field.
- Branch, pin, and roll back a prompt: the versioning RPCs as a workflow.
- Secure a server: tokens, TLS, and the broker token.
- Client SDKs: compare what the Python and Node SDKs wrap.