Skip to main content

gRPC API

The Priompt server exposes one gRPC service, priompt.v1.PromptService, defined in proto/priompt/v1/prompt.proto in the proto repository. The SDKs, the CLIs, and the web UI all call these eleven RPCs.

RPCs​

RPCWritesDescription
GetPromptNoFetch the served version of a prompt, or a pinned branch or commit.
ListPromptsNoList the served prompts under a URI prefix.
DiffPromptNoSemantic diff of the served version against an edited template.
PublishPromptYesValidate and commit a new version to a branch.
HistoryNoCommit log of a branch, newest first.
ListBranchesNoEvery branch of a prompt and its tip.
ListCommitsNoEvery commit of a prompt, including commits no branch reaches.
CreateBranchYesCreate a branch at another branch's tip.
MergeBranchYesMerge one branch into another with a merge commit.
DiffCommitsNoSemantic diff between any two commits.
SetBranchYesPoint a branch at an existing commit, to roll back or pin.

Conventions​

  • Auth: Send the metadata header authorization: Bearer <token> when the server has auth on. Every RPC checks that the token's org matches the URI's org. The RPCs marked Writes also need a token with write access. See Errors.
  • Branches: An empty branch field means main. Only main is served: changes to other branches don't move the served version, clear the cache, or notify subscribers.
  • Hashes: version_hash is the SHA-256 of a prompt's content (template and slots). hash and commit_hash identify a commit: the SHA-256 of its URI, content hash, parents, author, and message. Every hash is 64 hex characters, and RPCs only accept full commit hashes. See the Glossary.
  • Errors: Standard gRPC status codes. Each RPC section lists its own; Errors has the cause and fix for each.
  • Reflection: The server doesn't register gRPC reflection, so tools such as grpcurl need the .proto file.

The examples use grpcurl from a checkout of the proto repository against a local server:

call() {
grpcurl -plaintext -import-path proto -proto priompt/v1/prompt.proto \
-H "authorization: Bearer $PRIOMPT_TOKEN" \
-d "$2" localhost:8443 "priompt.v1.PromptService/$1"
}

grpcurl takes and prints fields in lowerCamelCase (versionHash) and omits fields that hold their default value. Examples ran against a server without auth, which records commit authors as anonymous.

GetPrompt​

Returns the served version of a prompt (the tip of main), or the version at ref. Without ref, the response comes from the server cache when it can.

Request: GetPromptRequest

FieldTypeDescription
uristringPrompt address, priompt://<org>/<path>.
refstringOptional. A branch name, or a full commit hash of this prompt. Empty returns the served version.

Response: GetPromptResponse

FieldTypeDescription
uristringThe prompt address.
templatestringThe template, with {slot} placeholders.
slotsrepeated stringThe slot names the template declares.
version_hashstringHash of the content.
commit_hashstringThe commit served. Set only when ref is set.

Errors: NotFound, DataLoss, PermissionDenied.

call GetPrompt '{"uri":"priompt://acme/support/agent","ref":"refunds"}'
Output
{
"uri": "priompt://acme/support/agent",
"template": "You are a support agent for {org}.\nAnswer billing and refund questions only.\nBe polite.\n",
"slots": [
"org"
],
"versionHash": "0c07a41e74813f83275d38037df660b3416afa2473ad3d42c3f44e911855edac",
"commitHash": "4498a4bc2f408ddfc7f2565ee5ab037fd1598476a3a6fc00205c1ca3e2f00641"
}

ListPrompts​

Returns the served prompts whose URI starts with prefix, sorted by URI. A "repo" is a prefix: split the URIs on / to build a tree.

Request: ListPromptsRequest

FieldTypeDescription
prefixstringURI prefix, such as priompt://acme/support/. Empty lists every prompt, which only an admin token may do.

Response: ListPromptsResponse

FieldTypeDescription
entriesrepeated PromptEntryOne entry per prompt: uri and version_hash.

With an org-scoped token, an empty prefix lists the token's org.

Errors: PermissionDenied when an org-scoped token lists outside priompt://<org> or priompt://<org>/....

call ListPrompts '{"prefix":"priompt://acme/"}'
Output
{
"entries": [
{
"uri": "priompt://acme/onboarding/welcome",
"versionHash": "22e5cc10ac0f3d70fd97c6b554a36abcb3173731412212dc222106e9cbcac402"
},
{
"uri": "priompt://acme/support/agent",
"versionHash": "0085fceb6d1d12a6a399bcaef2c40bb20a581966354ee2385b1d99f33c7ca247"
}
]
}

DiffPrompt​

Runs the semantic diff between the served version and an edited template, with the server's embedding model. Nothing is stored.

Request: DiffPromptRequest

FieldTypeDescription
uristringThe stored prompt, the original side of the diff.
new_templatestringThe edited template.

Response: DiffPromptResponse, a list of Change messages, one per changed region. An empty list means no change.

Errors: NotFound, Internal (diff failed, when the embedding endpoint fails), PermissionDenied.

call DiffPrompt '{"uri":"priompt://acme/support/agent","newTemplate":"You are a support agent for {org}.\nAnswer billing and refund questions only.\nBe polite.\n"}'
Output
{
"changes": [
{
"oldStart": 1,
"oldEnd": 2,
"newStart": 1,
"newEnd": 2,
"kind": "replace",
"pointDelta": 0.18350341907227385,
"up": [
{
"radius": 2,
"delta": 0.0658012670061725
}
],
"down": [
{
"radius": 2,
"delta": 0.1339745962155613
}
],
"upBoundary": true,
"downBoundary": true,
"classification": "localized tweak"
}
]
}

Change​

FieldTypeDescription
old_start, old_endint32The changed lines in the original, as a 0-based, half-open range.
new_start, new_endint32The changed lines in the edit, as a 0-based, half-open range.
kindstringreplace, insert, or delete.
point_deltadoubleMeaning shift at the changed lines, from 0 to 1.
up, downrepeated WindowHow the shift spreads above and below the change. Each Window has a radius in lines and a delta.
up_boundary, down_boundarybooltrue when that curve reached the start or end of the template before it flattened.
classificationstringThe verdict: minor edit, localized tweak, or structural.

How the signals and verdicts work is in Semantic diff.

PublishPrompt​

Validates the prompt and commits it to a branch. On main it also moves the served version, clears the cache, and notifies subscribers with the verdict of the change. Publishing content that equals the served version of main is a no-op: no commit, no event, and the same version_hash.

Request: PublishPromptRequest

FieldTypeDescription
uristringPrompt address.
templatestringThe template.
slotsrepeated stringEvery slot the template uses, and no others.
messagestringOptional commit message.
branchstringTarget branch. Empty means main.

Response: PublishPromptResponse

FieldTypeDescription
version_hashstringHash of the published content.

Errors: InvalidArgument, PermissionDenied, Aborted, Unavailable.

The commit's author is the JWT sub claim, else the static token's org, else anonymous.

call PublishPrompt '{"uri":"priompt://acme/support/agent","template":"You are a support agent for {org}.\nAnswer billing questions only.","slots":["org"],"message":"first version"}'
Output
{
"versionHash": "0085fceb6d1d12a6a399bcaef2c40bb20a581966354ee2385b1d99f33c7ca247"
}

History​

Returns a branch's commits, newest first, following first parents only (like git log --first-parent).

Request: HistoryRequest

FieldTypeDescription
uristringPrompt address.
branchstringBranch. Empty means main.

Response: HistoryResponse with commits, a list of Commit:

FieldTypeDescription
hashstringCommit hash.
version_hashstringHash of the content at this commit.
parentstringPrevious commit on the branch. Empty for the first commit.
parent2stringThe merged branch's tip. Set only on merge commits.
authorstringWho published it.
messagestringCommit message.
created_atstringUTC timestamp in RFC 3339 with variable-length fractional seconds (Go's RFC3339Nano), for example 2026-10-18T09:41:10.123456Z. Don't assume a fixed width.

Errors: NotFound (branch not found), PermissionDenied.

call History '{"uri":"priompt://acme/support/agent"}'
Output
{
"commits": [
{
"hash": "7243eec584c5c7475942b4b21d453b4c73120bbb3496dd883244b66d1a7c3ce8",
"versionHash": "fe8bf00e2bce93f6dc5112bcaf5595a59515054e688f1be2dfc8b3e22fcf70a4",
"parent": "360bb2f4f27076bee7f99c0e6533b801982956c7e4b06ef5a66c437e1cbc9fbb",
"author": "anonymous",
"message": "add tone",
"createdAt": "2026-10-18T04:45:25.5540023Z"
},
{
"hash": "360bb2f4f27076bee7f99c0e6533b801982956c7e4b06ef5a66c437e1cbc9fbb",
"versionHash": "0085fceb6d1d12a6a399bcaef2c40bb20a581966354ee2385b1d99f33c7ca247",
"author": "anonymous",
"message": "first version",
"createdAt": "2026-10-18T04:45:11.3913954Z"
}
]
}

ListBranches​

Returns every branch of a prompt and the commit it points at, sorted by name. Requires v0.7.4 or later.

Request: ListBranchesRequest

FieldTypeDescription
uristringPrompt address.

Response: ListBranchesResponse with branches, a list of Branch:

FieldTypeDescription
namestringBranch name.
commit_hashstringThe commit the branch points at.

An address with no commits returns an empty list.

Errors: PermissionDenied.

call ListBranches '{"uri":"priompt://acme/support/agent"}'
Output
{
"branches": [
{
"name": "main",
"commitHash": "a83cea97db1650976e34204aa16d5121c24c8ed191adc54bf2ee24803af6ea1e"
},
{
"name": "refunds",
"commitHash": "12a1f29fb268a3b728739ad204b6b58ce7efaa170d4030c4f9d0f589615bba1e"
}
]
}

ListCommits​

Returns every commit of a prompt, newest first, never listing a commit before its children. Unlike History, it includes commits that no branch reaches, such as the commits after the one you rolled main back to, so you can roll forward to them with SetBranch. Requires v0.7.4 or later.

Request: ListCommitsRequest

FieldTypeDescription
uristringPrompt address.

Response: ListCommitsResponse with commits, a list of Commit (see History). An address with no commits returns an empty list.

Errors: PermissionDenied.

In this example, main was rolled back to first version, so History lists only that commit:

call ListCommits '{"uri":"priompt://acme/support/agent"}'
Output
{
"commits": [
{
"hash": "12a1f29fb268a3b728739ad204b6b58ce7efaa170d4030c4f9d0f589615bba1e",
"versionHash": "f0100398ecdf28b0e7452dc150fd45d70a02e0a663c0e3002352d9daef80df25",
"parent": "a5d2e29b37bde3f3ea2f32c3e40e094fdb37a6b1a5906789cdc4157fda59adaa",
"author": "anonymous",
"message": "handle refunds",
"createdAt": "2026-10-18T23:24:18.611142389Z"
},
{
"hash": "a5d2e29b37bde3f3ea2f32c3e40e094fdb37a6b1a5906789cdc4157fda59adaa",
"versionHash": "03e3bb48f55d17fd620dffad0211741bdf2383a22ce7c9ab27a29b4c120c3aab",
"parent": "a83cea97db1650976e34204aa16d5121c24c8ed191adc54bf2ee24803af6ea1e",
"author": "anonymous",
"message": "add tone",
"createdAt": "2026-10-18T23:24:18.426825214Z"
},
{
"hash": "a83cea97db1650976e34204aa16d5121c24c8ed191adc54bf2ee24803af6ea1e",
"versionHash": "77d71a4d50ee6bd134a7bc6865be21292042d9be7676e5f271894294cb9c533b",
"author": "anonymous",
"message": "first version",
"createdAt": "2026-10-18T23:24:18.336077361Z"
}
]
}

CreateBranch​

Creates a branch that points at the tip of another branch.

Request: CreateBranchRequest

FieldTypeDescription
uristringPrompt address.
namestringNew branch name. Required.
fromstringSource branch. Empty means main.

Response: CreateBranchResponse

FieldTypeDescription
commit_hashstringThe commit the new branch points at.

Errors: InvalidArgument (branch name required), AlreadyExists, NotFound, PermissionDenied.

call CreateBranch '{"uri":"priompt://acme/support/agent","name":"refunds"}'
Output
{
"commitHash": "7243eec584c5c7475942b4b21d453b4c73120bbb3496dd883244b66d1a7c3ce8"
}

MergeBranch​

Merges from into into and records a merge commit with two parents. The merge takes the content of from; there's no three-way content merge. Merging into main moves the served version, clears the cache, and notifies subscribers with the verdict when the content changes.

Request: MergeBranchRequest

FieldTypeDescription
uristringPrompt address.
intostringTarget branch. Empty means main.
fromstringSource branch. Required.
messagestringOptional commit message.

Response: MergeBranchResponse

FieldTypeDescription
commit_hashstringThe merge commit.

Errors: NotFound (branch not found, also when from is empty), Aborted, Unavailable, PermissionDenied.

call MergeBranch '{"uri":"priompt://acme/support/agent","from":"refunds","message":"ship refunds"}'
Output
{
"commitHash": "9c5623c2b72764219b216a469f4b757d906fc1fff6a77b8a8d254b05f39b9e65"
}

DiffCommits​

Runs the semantic diff between two commits of the prompt at uri. Both commits must belong to that prompt; a commit of any other prompt returns commit not found. The response has the same shape as DiffPrompt.

Request: DiffCommitsRequest

FieldTypeDescription
uristringPrompt address.
from_hashstringThe original commit.
to_hashstringThe edited commit.

Response: DiffPromptResponse, a list of Change messages.

Errors: NotFound (commit not found), Internal, PermissionDenied.

call DiffCommits '{"uri":"priompt://acme/support/agent","fromHash":"7243eec584c5c7475942b4b21d453b4c73120bbb3496dd883244b66d1a7c3ce8","toHash":"4498a4bc2f408ddfc7f2565ee5ab037fd1598476a3a6fc00205c1ca3e2f00641"}'

The output is one replace change classified localized tweak, like the DiffPrompt example.

SetBranch​

Points a branch at an existing commit of the same prompt. On main this is a rollback: the served version changes at once, the cache is cleared, and subscribers are notified with the verdict of the change. Nothing is deleted, and the later commits stay reachable by hash.

Request: SetBranchRequest

FieldTypeDescription
uristringPrompt address.
branchstringBranch to move. Empty means main.
commit_hashstringFull hash of the commit to point at. Required.

Response: SetBranchResponse

FieldTypeDescription
version_hashstringHash of the content the branch now holds.

Errors: InvalidArgument (commit_hash required), NotFound, Unavailable, PermissionDenied.

call SetBranch '{"uri":"priompt://acme/support/agent","commitHash":"7243eec584c5c7475942b4b21d453b4c73120bbb3496dd883244b66d1a7c3ce8"}'
Output
{
"versionHash": "fe8bf00e2bce93f6dc5112bcaf5595a59515054e688f1be2dfc8b3e22fcf70a4"
}

Change events​

When main moves, the server publishes an event on its embedded NATS broker (-nats-addr). The subject is priompt. followed by the URI's segments joined by ., with every byte other than a letter, a digit, _, or - percent-encoded inside a segment: priompt://acme/support/agent becomes priompt.acme.support.agent, and priompt://acme.corp/x/a.b becomes priompt.acme%2Ecorp.x.a%2Eb. The payload is JSON:

{"version":"222aa819c4988059c57f9c8805fdd451cc76dac2fdc875a98a6b2bfe86896c1a","classification":"structural"}
  • version: The new version hash.
  • classification: new for a first publish, else the worst verdict of the change. Absent when the server couldn't compute one.

priompt watch and the SDKs' subscribe methods read these events. For how to act on them, see Hot-reload prompts.