polycore.jsondeclares the capability surface and project context.- The
actions/directory contains customer-authored capabilities. - Runtime variables bind one deployed process to one project and environment.
- Your deployment resolves credentials through workload identity or secret injection.
Polycore prepares this package with you during early access. This reference
exists so engineering and security teams can review exactly what is committed
and what remains runtime-only.
Repository layout
polycore-runner
polycore.json
actions
context
schema
Dockerfile
package.json
actions/ beside polycore.json; there is no action-directory
setting.
Complete example
polycore.json
polycore.json, not
from the process’s current working directory.
Four conventions
The file follows the same four rules throughout, so a family you have not used before behaves the way you would guess.1
Presence enables reads
"auth": {} exposes the Auth read family. There is no true shorthand:
one shape per family means nothing has to ask whether a config is a boolean
or an object.2
`write` is the write grant, and it names the identity
Absent means read-only.
"ambient" uses Application Default Credentials.
{ "keyEnv": "…" } uses a separate service-account key, so the runtime
identity can stay read-only at IAM. Everything a grant unlocks is
write-hazard and still needs a human approval per call.3
Every environment binding is a `*Env` field
No variable name is hardcoded in the runner, so you can rename any of them
without a code change. Most default to one conventional name; the Firebase
project id instead falls back to Google’s own resolution order, because a
GCP runtime already populates it under more than one name.
4
Every ceiling lives under `limits`
If a value bounds how much work one call may do, it is in that object and
nowhere else.
integrations here means your systems, reached only from inside your
environment. It is unrelated to Polycore’s hosted integrations (Notion and
friends), which are provider grants the control plane holds.Configuration fields
object
default:"{}"
The customer systems this runner exposes. Every family is read-only unless it
carries a
write grant. Omit for a runner that serves only customer-authored
actions.Firebase
object
The Firebase project this runner serves, and which of its services are
exposed. The three services are independent grants against one project: a
runner may serve document reads without ever exposing the auth directory.
string
The variable holding the GCP project id, when you want to name one. Omit it
and the runner uses Google’s own resolution order —
FIRESTORE_PROJECT_ID,
then GOOGLE_CLOUD_PROJECT, then GCLOUD_PROJECT — which is what GCP
runtimes already populate. The explicit variable comes first on purpose: an
operator who sets one means it, and it should not lose to whichever project
the VM happens to sit in.Name a variable when the runner reads a different Firebase project than the
one it runs in, or when your deployment uses its own spelling. Naming one
means only that one: there is no quiet fallback behind it.string
Path to a build-generated Typesync definition JSON, relative to
polycore.json. The runner validates and reads this file locally, and it
grounds the agent in your declared schema instead of one inferred from sampled
documents."ambient" | { keyEnv }
Grants the approval-gated
firestore.create / set / update / delete /
batchWrite capabilities.object
Exposes
auth.* directory reads. See Firebase
Auth."ambient" | { keyEnv }
Grants the approval-gated account-administration and action-link capabilities.
{keyEnv} lets the runtime service account stay roles/firebaseauth.viewer.object
Exposes
storage.* object reads. See Firebase
Storage.string
default:"FIREBASE_STORAGE_BUCKET"
Where the project’s default bucket name comes from, used whenever a Storage
capability names no bucket.
string[]
The buckets in scope. A runtime service account often has object access to
buckets unrelated to the product (build artifacts, Terraform state, backups);
naming the ones in scope keeps the capability surface narrower than the IAM
grant behind it. Absent means every reachable bucket. The default bucket must
appear in this list when it is set.
integer
default:"60"
Longest life of a signed read URL.
0 withdraws storage.getSignedUrl
entirely, so it is never advertised.integer
default:"1048576"
Largest object
storage.download returns inline. Larger objects need a signed
URL.integer
default:"1048576"
Largest inline object
storage.upload accepts, decoded.integer
default:"1000"
Objects one
storage.summarize walk covers before it stops and reports
complete: false."ambient" | { keyEnv }
Grants the approval-gated
storage.delete / copy / move / setMetadata /
makePublic / upload capabilities. Writes resolve their bucket through the
same allowlist as reads, so a write can never reach a bucket a read could not.Postgres
object
Exposes
postgres.* bounded schema discovery, explain, and parameterized
read-only queries. See Postgres.string
default:"POLYCORE_POSTGRES_URL"
Where the connection string comes from. Point it at a read-only role or
replica.
object
Grants
postgres.update and postgres.delete. Absent means read-only, as
with every other family. Present with no urlEnv means writes go through the
read connection; give urlEnv to use a separate write role so the read path
stays mutation-incapable at the database. See Postgres
writes.string
Where the write connection string comes from. Omit to reuse
integrations.postgres.urlEnv, which is only appropriate when that role
already has write access.object
Ceilings on write review cost, separate from the read limits because they
bound what a human can reasonably approve rather than what the database can
reasonably serve.
proposalTtlMinutes bounds how long a decision stays open, not correctness:
every previewed row is pinned to the version it had at preview time, so a row
written in the meantime aborts the apply whatever the clock says.object
Customer-reviewed upper bounds. Every value is a ceiling: a call may request
less, never more. Unset ceilings take their defaults.
PostHog and Prometheus
object
Exposes
posthog.* read capabilities. host is committed; the project id and
API key bind from projectIdEnv (default POSTHOG_PROJECT_ID) and
apiKeyEnv (default POSTHOG_PERSONAL_API_KEY).integer
default:"365"
Longest window the actor-oriented helpers accept. Raw HogQL stays explicit.
object
Exposes
prometheus.* read capabilities against baseUrl. auth is
{ "type": "none" }, { "type": "bearer", "tokenEnv": "…" }, or
{ "type": "basic", "usernameEnv": "…", "passwordEnv": "…" }. An optional
tenantHeader sets a safe header such as X-Scope-OrgID from valueEnv.Everything else
{ file } | { text }
Agent grounding for this project.
{ "file": "./context/product.md" } is
preferred for anything longer than a line; { "text": "…" } inlines it. Two
shapes rather than two sibling keys, so “both were set” is not a state the
parser has to reject.record<string, string>
Optional secret values for customer-authored actions, keyed by the names the
actions declare. Missing keys fall back to
process.env. Values in the file
take precedence over the environment.object
Optional control-plane URL and enrollment identity. Production deployments
normally supply these fields through environment variables instead.
object
Opts the runner into
code.execute delegated workloads. It sets the workload
image, OCI runtime (runsc by default), container CLI, and maximum CPU,
memory, process, and timeout limits.Runtime identity
These bindings identify the deployed process and its control-plane enrollment:string
Path to the committed
polycore.json. Set this when the runner command does
not receive --config <path>.string
required
The control-plane project namespace this runner serves.
string
required
The runner WebSocket endpoint, using
wss:// in production.string
required
The runner registration provisioned for this project and environment.
secret
required
Authenticates the runner’s join handshake.
secret
required
Lets the runner verify dispatch envelopes signed for its registration.
polycore.json and is not selected by capability arguments.
Datastore bindings
Every one of these is the default variable name for a*Env field. Rename
any of them in polycore.json rather than working around it.
- Postgres
- Firebase
- PostHog
- Action secrets
secret
Required when
integrations.postgres is present. Point it at a read-only
role or replica and inject it through your secret manager. Renamed with
integrations.postgres.urlEnv.Project context
Project context explains customer-specific facts the fixed Polycore agent prompt should not contain. Keep it concise and operational:context/product.md
- Domain terms and identifiers.
- Important data-model conventions.
- Safe interpretations of ambiguous language.
- Known limits or preconditions that apply across requests.
Configuration lifecycle
1
Review
Query families, context changes, and actions are reviewed in your runner
repository.
2
Build
The image includes
polycore.json, actions, context, and any generated
schema artifact.3
Inject
CI or infrastructure tooling supplies enrollment and execution secrets
without rewriting structural config.
4
Deploy
The environment’s long-running runner process starts or restarts.
5
Advertise
On connection, the runner sends the current catalog and project context to
the control plane.
polycore.json, actions, or
project context. A standing authority change remains a code and deployment
change.

