As the Truffle is using a self-signed certificate, you'd need to either use port 80 without SSL or port 443 without certificate validation. In examples, the latter option will be used.
Truffle exposes it's API via GRPC, also a subset of the API is mapped to plain REST endpoints.
You will need curl
, grpcurl
and optionally jq
for prettifying responses.
On Mac OS:
brew install curl grpcurl jq
On Linux:
apt install curl jq
snap install grpcurl
For convenience, run the following in bash or zsh:
export TRUFFLE=forecast.itsalltruffles.com:443
truffle-rpc() {
grpcurl -insecure -use-reflection "$@"
}
To prettify curl responses, append -k -D /dev/stderr | jq .
to the end of curl command.
For example:
curl -X POST "https://${TRUFFLE}/v1/users:register" \
-k -D /dev/stderr | jq .
We'll be omitting the formatting in examples.
To list available services, run:
truffle-rpc $TRUFFLE list
Result:
grpc.health.v1.Health
grpc.reflection.v1.ServerReflection
grpc.reflection.v1alpha.ServerReflection
truffle.hyphae.api.HyphaeAPI
truffle.os.TruffleOS
To list all methods of a service, run:
truffle-rpc $TRUFFLE describe truffle.os.TruffleOS
Pass service name as the last argument.
To request a specific method signature, run:
truffle-rpc $TRUFFLE describe truffle.os.TruffleOS.Client_RegisterNewUser
Result:
truffle.os.TruffleOS.Client_RegisterNewUser is a method:
rpc Client_RegisterNewUser ( .truffle.os.RegisterNewUserRequest ) returns ( .truffle.os.RegisterNewUserResponse ) {
option (.google.api.http) = { post: "/v1/users:register", body: "*" };
}
It also returns a REST endpoint name. We will show how to use REST endpoints later.
Request parameter details:
truffle-rpc $TRUFFLE describe truffle.os.RegisterNewUserRequest
truffle-rpc $TRUFFLE describe truffle.os.ClientMetadata
Result:
truffle.os.RegisterNewUserRequest is a message:
message RegisterNewUserRequest {
.truffle.os.ClientMetadata metadata = 1;
optional string user_id = 2;
}
truffle.os.ClientMetadata is a message:
message ClientMetadata {
string platform = 1;
optional string version = 2;
optional string device = 3;
}
Request response details:
truffle-rpc $TRUFFLE describe truffle.os.RegisterNewUserResponse
Result:
truffle.os.RegisterNewUserResponse is a message:
message RegisterNewUserResponse {
string user_id = 1;
string token = 2;
}
Let's try calling different methods simulating a typical client workflow.
Start by registering a new user.
To register a user you can either call a GRPC method or a REST endpoint. With GRPC:
truffle-rpc $TRUFFLE truffle.os.TruffleOS.Client_RegisterNewUser
A user id will be assigned randomly. You can pass a specific one as well:
truffle-rpc -d '{ "user_id": "123456" }' $TRUFFLE truffle.os.TruffleOS.Client_RegisterNewUser
Or https:
curl -k -X POST "https://$TRUFFLE/v1/users:register" -d '{ "user_id": "123456" }'
Response:
{"user_id":"123456","token":"da110593-7589-4646-a82f-6fc353c699a4"}
Initial session is also created for the user and it's token is returned. This token will be used to authorize all other requests, so please save it.
From now on we'll assume that session token is saved in variable TRUFFLE_SESSION
.
export TRUFFLE_SESSION=da110593-7589-4646-a82f-6fc353c699a4
To authorize requests, pass the token in session
header field:
truffle-rpc -H "session: $TRUFFLE_SESSION" $TRUFFLE method-name
New sessions can be created by authorizing session creation from the device with active session. If there are no active sessions left, recovery codes can be used.
Generate a set of recovery codes:
truffle-rpc -H "session: $TRUFFLE_SESSION" $TRUFFLE truffle.os.TruffleOS.Client_GetUserRecoveryCodes
Truffle informs user of any actions occuring like app install start, success, failure, etc.
SESSION_READY
is the most important notification. After it's received, it's possible to start making actual requests.
Subscribe to notifications:
truffle-rpc -H "session: $TRUFFLE_SESSION" $TRUFFLE truffle.os.TruffleOS.SubscribeToNotifications
Result:
{
"type": "SESSION_READY",
"none": {}
}
Call:
truffle-rpc -H "session: $TRUFFLE_SESSION" $TRUFFLE truffle.os.TruffleOS.App_GetListOfAllApps
Result:
ERROR:
Code: NotFound
Message: No apps found
Lets install our first app.
This is automated by the CLI provided with the SDK, but for the curious here is what running hyphae upload MyApp
does under the hood.
- Client calls
truffle.os.TruffleOS.App_InstallApp
- Client creates/reserves an app builder, registers their app, gets token to upload app to builder.
- Client uploads app to
/install/<returned token>
- Client monitors progress via direct logs returned from
/install/<token>
and/or notifications on a stream acquired fromtruffle.os.SubscribeToNotifications
Example Install Payload
{
"app_id": "", //this is a new app so this is left empty, assigned ID will be returned
"app_info": {
"description": "Helps you research things!",
"name": "Research"
// as well, icon can be provided here, but
// other fields will be deduced from the app automatically
},
"prev_build_id": "", // provide this to reuse a previous build cache if available!
"make_default": false // should this app be available for all users of the Truffle ?
}
truffle-rpc -H "session: $TRUFFLE_SESSION" -d '<example payload>' $TRUFFLE truffle.os.TruffleOS.App_InstallApp
Then, a request with said payload would return something like:
{
"token": "VlVTV1dTVVNWVV5fWlpaWl9WXFpaWFtbW1dV.lbvVRRqLQEdJJ3YYAQIbWScQA4G8xxcgrw56hpa",
"build_id": "91c567e7_eb00_4049_9537_e8eea53b0206",
"app_id": "16c688d7-eed9-41b2-b001-d63377d11932"
}
The returned app_id should be stored for future updating / referral to this app.
The returned build_id can be cached to reuse the buildcache for future updates.
The returned token should then be used to POST the app bundle (.hyphae file) to /install/<token>
# example of the POST to upload app bundle using returned values from App_Install RPC.
APPBUNDLEPATH="~/Research.hyphae"
BUILD_ID="91c567e7_eb00_4049_9537_e8eea53b0206"
INSTALL_TOKEN="VlVTV1dTVVNWVV5fWlpaWl9WXFpaWFtbW1dV.lbvVRRqLQEdJJ3YYAQIbWScQA4G8xxcgrw56hpa"
curl -k -X POST "$TRUFFLE" \
-H "Build-ID: $BUILD_ID" \
--data-binary @"$APPBUNDLEPATH" \
--no-buffer
This endpoint returns logs of the build process via SSE.
As well, notifications with progress are sent on the stream acquired with truffle.os.TruffleOS.SubscribeToNotifications
to all of a user's active sessions/devices. These notifications have associated_id
set to the build ID, and install_progress
set as the payload field with a
truffle.os.AppInstallProgress
message with the latest updates. These notifications will also have one of APP_INSTALL_START, APP_INSTALL_PROGRESS, APP_INSTALL_FAILURE, APP_INSTALL_SUCCESS
as the notification type respectively.
Once installation is complete, the POST upload request to the builder will display success or error logs, and either a APP_INSTALL_FAILURE
or APP_INSTALL_SUCCESS
notification corresponding to the build ID will have been sent as well.
Now, assuming successful install, requesting a list of apps returns:
{
"apps": [
{
"app_id": "1413c8a5-46dc-48e0-af8d-a37e8211beef",
"name": "Research",
"description": "Research application",
"icon": {
"png_data": "..."
To update the app, the same steps are followed, however one should now pass the "app_id"
that was returned during the initial installation, and the "previous_build_id"
if known to potentially save time building and applying the update in turn.
Note: Pending SDK specific documentation will cover more details about formatting of app bundles and the API/spec to implement your own SDK / runtime as well.
Run:
truffle-rpc -d '{ "new_task": { "app_id": "1413c8a5-46dc-48e0-af8d-a37e8211beef", "user_message": { "content": "What time is it?" } } }' \
-H "session: $TRUFFLE_SESSION" $TRUFFLE truffle.os.TruffleOS.Task_OpenTask
You can also upload files and attach them to a task using files
field.
This call will open a new stream with events related to task progress. In this case:
{
"task_id": "3458f546-a6e0-4d1a-8716-0df00248636a",
"info": {
"info": {
"run_state": "TASK_RUN_STATE_CREATING_NEW",
"app_id": "1413c8a5-46dc-48e0-af8d-a37e8211beef",
"app_version": "null",
"options": {
"think_opts": {
"cot_summaries_min_interval": "60.100s",
"cot_summaries_min_chars": 55
},
"model_uuid": "72fc6ff6-93fb-4528-af95-5fdea75aad87"
},
"created": "2025-08-15T15:35:13.977213918Z"
}
}
}
{
"task_id": "3458f546-a6e0-4d1a-8716-0df00248636a",
"nodes": [
{
"node": {
"id": 1,
"parent_id": 1,
"user_msg": {
"content": "What time is it?"
}
}
}
],
"task_flags": 1
}
{
"task_id": "3458f546-a6e0-4d1a-8716-0df00248636a",
"info": {
"info": {
"run_state": "TASK_RUN_STATE_CREATING_NEW",
"task_title": "Current Time Needed"
}
}
}