Secrets
Stored values the agent can use without ever reading them
On this page(14 sections)
- Store a secret
- Names of the stored secrets
- Make and store a random secret
- Delete a secret
- Every secret this sandbox holds, from everywhere
- Show one secret's value
- Which credentials need somebody's approval
- Put a credential behind named approvers
- Stop requiring approval for a credential
- Which secrets are host-guarded, and where they may go
- Turn a secret's host guard on or off, and set its hosts
- How a connection's credential reaches the agent, and what it may do
- Set how a connection's credential reaches the agent, and its rules
- Ask a named person to release a credential
Write a secret, list which names exist, delete one. Revealing a value is the deliberate exception and the only route that hands one back; everywhere else the daemon substitutes a secret by reference at the moment a command runs.
14 calls. Pick one to open it, or use the list on the right.
POST/secretsStore a secret
Writes one name and value where the agent's references resolve it, without a restart: desired-state/.env once DevOps is active, the sandbox's own secret store before that.
What you send
| Field | Type | Where |
|---|---|---|
keyrequiredThe name to store it under,… | string | body |
valuerequiredThe value | string | body |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X POST "$SANDBOX/secrets" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"key":"OPENAI_API_KEY","value":"…"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.set({
"key": "OPENAI_API_KEY",
"value": "…"
});GET/secretsNames of the stored secrets
Which secrets exist here. Names only, never values.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
keysThe names that exist here | string[] |
curl "$SANDBOX/secrets" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.list();POST/secrets/generateMake and store a random secret
Makes a random value and stores it under a new name, where `set` would have put it, for a secret nobody has to find or paste (a session key, a signing secret, a password the task sets up itself). Answers the name and its length, never the value. Refused for a name something here already holds.
What you send
| Field | Type | Where |
|---|---|---|
keyrequiredThe name to store it under:… | string | body |
bytesHow much randomness, in bytes | integer | body |
formatHow it is spelled: `hex` (0-9,… | "hex" | "base64url" | "alnum" | body |
What comes back
| Field | Type |
|---|---|
keyThe name it is stored under | string |
lengthHow many characters it is, which… | integer |
storedWhere it was kept: desired-state/.env once… | "env" | "sandbox" |
curl -X POST "$SANDBOX/secrets/generate" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"key":"OPENAI_API_KEY","bytes":32,"format":"hex"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.generate({
"key": "OPENAI_API_KEY",
"bytes": 32,
"format": "hex"
});DELETE/secrets/{key}Delete a secret
Removes one by name.
What you send
| Field | Type | Where |
|---|---|---|
keyrequiredWhich secret, by name | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X DELETE "$SANDBOX/secrets/OPENAI_API_KEY" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.remove({
"key": "OPENAI_API_KEY"
});GET/secrets/inventoryEvery secret this sandbox holds, from everywhere
One view across all the places secrets live here: what exists, where it came from and whether it is working. Never any values. This one always answers, even before there is a store to write to.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
entriesOne entry per secret this sandbox… | object[] |
keyWhat identifies it | string |
kindWhere it came from: you set… | "env" | "generated" | "capability" | "provider" |
labelA friendlier name, for entries that… | string |
statusWhether it exists and, for a… | "missing" | "set" | "connected" |
requiredByWhat is waiting on it | object[] |
resourceIdWhich resource | string |
typeWhat kind of resource it is | string |
storedAtWhere it actually lives, in words | string |
revealableWhether its value can be shown… | boolean |
ciWhether a copy has been given… | object |
syncedWhether the pipeline has it | boolean |
pushedAtWhen it was last sent there | string |
lastUseThe last time an agent actually… | object |
atWhen, in milliseconds | number |
laneHow it was used: a command,… | "shell" | "code" | "browser" | "gateway" … (5) |
detailWhere it went: the start of… | string |
approvedByWho released it for that use,… | string |
credentialHow the agent gets this connection's… | object |
deliveryHow the agent gets this connection's… | "gateway" | "raw" | "direct" | "ssh-agent" |
rulesWhat the credential may do through… | object[] |
methodsThe HTTP methods it covers (`DELETE`,… | string[] |
pathsThe paths it covers, below the… | string[] |
action`allow` forwards it, `ask` holds it… | "allow" | "ask" | "deny" |
whyOne line on what the rule… | string |
rulesFromWhose rules these are: the connector's… | "connector" | "owner" |
gateWho has to release this before… | object |
approversWho may release it, by email | string[] |
scopeHow far one release goes: `use`… | "use" | "conversation" |
hostsIts host guard | object |
guardWhether a use off the list,… | boolean |
listThe hosts it goes to unasked… | string[] |
sourceWho set it: the owner, or… | "owner" | "connector" |
curl "$SANDBOX/secrets/inventory" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.inventory();POST/secrets/revealShow one secret's value
The only call that hands a value back, and it is for the owner alone. Sent as a body rather than in the address, so the name never ends up in a log or a browser's history.
What you send
| Field | Type | Where |
|---|---|---|
keyrequiredWhich secret, by name | string | body |
What comes back
| Field | Type |
|---|---|
valueThe value itself | string |
curl -X POST "$SANDBOX/secrets/reveal" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"key":"OPENAI_API_KEY"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.reveal({
"key": "OPENAI_API_KEY"
});GET/secrets/gatesWhich credentials need somebody's approval
What is gated and who may release it. Names and addresses only, never values, and the agent may read it too: knowing a credential needs Bob is what stops it concluding the account is simply not connected.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
gatesEvery gate in force | object[] |
subjectWhat is gated: a secret's name,… | string |
kindWhether this gate covers one stored… | "secret" | "capability" |
approversExactly who may release it, by… | string[] |
scopeHow far one release goes: `use`… | "use" | "conversation" |
curl "$SANDBOX/secrets/gates" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.gates();PUT/secrets/gates/{subject}Put a credential behind named approvers
Names exactly who may release one secret or one connected account, and how far a single release goes. The owner's call alone. A signed-in browser or a mounted server cannot be released for one use, so those are always for the rest of the conversation.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredWhat is gated: a secret's name,… | string | address |
kindrequiredWhether this gate covers one stored… | "secret" | "capability" | body |
approversrequiredExactly who may release it, by… | string[] | body |
scoperequiredHow far one release goes: `use`… | "use" | "conversation" | body |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X PUT "$SANDBOX/secrets/gates/Fix%20the%20flaky%20parser%20test" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"kind":"secret","approvers":["…","…"],"scope":"use"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.setGate({
"subject": "Fix the flaky parser test",
"kind": "secret",
"approvers": [
"…",
"…"
],
"scope": "use"
});DELETE/secrets/gates/{subject}Stop requiring approval for a credential
Removes one gate, so the agent can use that credential the way it uses any other. The owner's call alone.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredWhich gate, by the secret name… | string | address |
What comes back
| Field | Type |
|---|---|
okAlways true | true |
curl -X DELETE "$SANDBOX/secrets/gates/Fix%20the%20flaky%20parser%20test" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.removeGate({
"subject": "Fix the flaky parser test"
});GET/secrets/hostsWhich secrets are host-guarded, and where they may go
Every secret and connected account whose host guard is set, on or off, and its hosts. With the guard on, a use aimed off the list, or anywhere a command's text does not show, asks a person first, whatever the safety judge says. Names and hosts only, never values.
What you send
Nothing. Call it as it is.
What comes back
| Field | Type |
|---|---|
guardsEvery secret whose host guard has… | object[] |
subjectWhich secret, by the name its… | string |
kindWhether this gate covers one stored… | "secret" | "capability" |
guardOn: a use off the list,… | boolean |
hostsWhere it goes without asking while… | string[] |
sourceWho set it: the owner, or… | "owner" | "connector" |
curl "$SANDBOX/secrets/hosts" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.hosts();PUT/secrets/hosts/{subject}Turn a secret's host guard on or off, and set its hosts
Replaces one secret's host guard. Anybody who may use secrets can turn it on or take hosts away; turning it off or adding a host is the owner's: from the agent it raises a card for the owner in the live conversation and waits for their answer.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredWhich secret, by name, or which… | string | address |
kindWhether the subject is a secret… | "secret" | "capability" | body |
guardrequiredWhether a use off the list,… | boolean | body |
hostsrequiredThe whole new list | string[] | body |
conversationIdWhich conversation to ask the owner… | string | body |
What comes back
| Field | Type |
|---|---|
guardWhether the guard is on now | boolean |
hostsWhere it goes without asking while… | string[] |
approvedByWho approved the change, when it… | string |
curl -X PUT "$SANDBOX/secrets/hosts/Fix%20the%20flaky%20parser%20test" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"kind":"secret","guard":true,"hosts":["sandbox-a1b2c3d4e5f6.intentic.dev","sandbox-a1b2c3d4e5f6.intentic.dev"],"conversationId":"nightly-changelog"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.setHosts({
"subject": "Fix the flaky parser test",
"kind": "secret",
"guard": true,
"hosts": [
"sandbox-a1b2c3d4e5f6.intentic.dev",
"sandbox-a1b2c3d4e5f6.intentic.dev"
],
"conversationId": "nightly-changelog"
});GET/secrets/policy/{subject}How a connection's credential reaches the agent, and what it may do
Whether the credential gateway holds this connection's credential or the agent is handed it, and the method and path rules the gateway enforces on every request it attaches it to. Names and rules only, never values.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredWhich gate, by the secret name… | string | address |
What comes back
| Field | Type |
|---|---|
subjectThe connection's id | string |
deliveryHow the agent gets this connection's… | "gateway" | "raw" | "direct" | "ssh-agent" |
rulesWhat the credential may do through… | object[] |
methodsThe HTTP methods it covers (`DELETE`,… | string[] |
pathsThe paths it covers, below the… | string[] |
action`allow` forwards it, `ask` holds it… | "allow" | "ask" | "deny" |
whyOne line on what the rule… | string |
rulesFromWhose rules these are: the connector's… | "connector" | "owner" |
curl "$SANDBOX/secrets/policy/Fix%20the%20flaky%20parser%20test" \
-H "x-intentic-control: $INTENTIC_TOKEN"import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.policy({
"subject": "Fix the flaky parser test"
});PUT/secrets/policy/{subject}Set how a connection's credential reaches the agent, and its rules
The owner's alone, and never the agent's: handing the agent the credential itself, or replacing what the gateway lets it do, is a decision about the credential, not a use of it.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredThe connection's id | string | address |
deliveryHand the agent the credential itself… | "gateway" | "raw" | body |
rulesThe owner's own rules, replacing the… | object[] | null | body |
methodsThe HTTP methods it covers (`DELETE`,… | string[] | body |
pathsThe paths it covers, below the… | string[] | body |
actionrequired`allow` forwards it, `ask` holds it… | "allow" | "ask" | "deny" | body |
whyOne line on what the rule… | string | body |
What comes back
| Field | Type |
|---|---|
subjectThe connection's id | string |
deliveryHow the agent gets this connection's… | "gateway" | "raw" | "direct" | "ssh-agent" |
rulesWhat the credential may do through… | object[] |
methodsThe HTTP methods it covers (`DELETE`,… | string[] |
pathsThe paths it covers, below the… | string[] |
action`allow` forwards it, `ask` holds it… | "allow" | "ask" | "deny" |
whyOne line on what the rule… | string |
rulesFromWhose rules these are: the connector's… | "connector" | "owner" |
curl -X PUT "$SANDBOX/secrets/policy/Fix%20the%20flaky%20parser%20test" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"delivery":"gateway","rules":[{"methods":["…","…"],"paths":["src/app.ts","README.md"],"action":"allow","why":"…"},{"methods":["…","…"],"paths":["src/app.ts","README.md"],"action":"ask","why":"…"}]}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.setPolicy({
"subject": "Fix the flaky parser test",
"delivery": "gateway",
"rules": [
{
"methods": [
"…",
"…"
],
"paths": [
"src/app.ts",
"README.md"
],
"action": "allow",
"why": "…"
},
{
"methods": [
"…",
"…"
],
"paths": [
"src/app.ts",
"README.md"
],
"action": "ask",
"why": "…"
}
]
});POST/secrets/requestAsk a named person to release a credential
Raises the release card in the live conversation and waits for one of the people named on it. Refused, rather than held, when there is nobody to ask: an unattended turn, no live conversation, or a click with no verified identity behind it.
What you send
| Field | Type | Where |
|---|---|---|
subjectrequiredWhat to ask for: the secret's… | string | body |
whyOne line on what it is… | string | body |
conversationIdWhich conversation to raise the card… | string | body |
What comes back
| Field | Type |
|---|---|
grantedAlways true: a refusal is an… | true |
approvedByWho released it | string |
messageWhat the grant means in practice,… | string |
curl -X POST "$SANDBOX/secrets/request" \
-H "x-intentic-control: $INTENTIC_TOKEN" \
-H "content-type: application/json" \
-d '{"subject":"Fix the flaky parser test","why":"…","conversationId":"nightly-changelog"}'import { sandbox } from "@intentic/sandbox-client";
const result = await sandbox.secrets.request({
"subject": "Fix the flaky parser test",
"why": "…",
"conversationId": "nightly-changelog"
});