| description | Use authenticated forge HTTP endpoints to manage products, repositories, execution, source evidence and project operations. |
|---|
The API prefix is /api/v1. Hosted installations use an OIDC access token with
the configured API audience. Browser sessions use the server's secure session
cookie and CSRF protection. The explicitly enabled local bootstrap also accepts
Authorization: Bearer <FORGE_API_TOKEN> from loopback clients. See
Sign in and manage project access for each mode.
Request and response bodies use JSON unless a route downloads an artifact or file. Project permissions apply to the authenticated identity. The actual running application's OpenAPI document is the authoritative schema.
New runs freeze settings.automatic_verification from GET /tools/policy.
The factory default is {"enabled": true, "max_continuations": 1}. The configured
window must be a positive finite integer. The existing administrator-only policy update accepts this
setting with the other tool settings. A frozen snapshot without this setting
does not grant automatic execution.
Older SDK/MCP policy writes that omit this setting preserve its current value.
An explicit renewal changes the current policy and requires a new exact adoption;
it retains every spent handoff and command slot. The separate four-attempt coding
stage limit remains unchanged.
A pending implementation request with typed kind: "verification" can ask
Forge to run all explicit, frozen run.commands through SandboxExecutor.
Request IDs, question text and context never select commands or grant access.
Product decisions, credentials, architecture and approval questions remain
manual. Current execution authority, cancellation, campaign scope, source,
provider and policy are checked again before effects and continuation.
Native command intents and receipts retain the actual commands and outcomes.
Known failing checks become bounded, clearly attributed factory feedback.
completed means every configured command has a known result, including any
failures; it does not mean the product passed acceptance. Unknown effects hold
without automatic replay. Source identity includes untracked public source and
uses the existing review exclusions for dependencies, private files, build
outputs and tool caches, including .cache. Those directories are not a place
to store application source.
Each completed, durably resumed handoff grants one additional coding task,
separate from the frozen repair budget. History is preserved, and the existing
four-attempt ceiling remains. A spent, revoked, stale or uncertain grant cannot
start another coding task. The factory response uses protected
responding_actor.version: 4 / authentication_method: "factory_verification"
with its handoff and source/command/policy/provider digests; it is not a human
answer. Pre-admission refusals have a separate verification_handoff_refused
event and leave the original question pending.
Older paused runs require explicit native adoption:
- Read
GET /runs/{id}/verification-handoffs/candidates?agent=codex(or another explicitly selected configured coding provider). - Retain one new 32-character
request_idand POST/runs/{id}/verification-handoffs/adoptionswithagentand the exactpending_request_digest,source_digest,commands_digest,policy_digestandprovider_digestfrom that read. - If the response is lost, read
GET /runs/{id}/verification-handoffs/adoptions/{request_id}. Do not generate a replacement ID or retry an uncertain command.
Adoption records the current native operator and exact request body. Reusing an ID with different content refuses. It binds only that pending question and partial source, not later questions. Selecting a provider explicitly captures its current configuration through the normal native handoff; old frozen provider executables and snapshots stay immutable. Host coding providers still require current administrator authority. Admission queues work for the normal Engine consumer and never executes commands in the HTTP request.
The Python SDK exposes verification_handoff_candidates,
adopt_verification_handoff and verification_handoff_adoption. These methods
perform one explicit request each and do not create IDs, apply a fallback or
resume a run implicitly.
The native operator routes are under
/runs/{run_id}/sandbox-executions/{execution_id}/unknown-command-acknowledgements:
| Method | Path | Purpose |
|---|---|---|
| GET | /candidate?agent=agentic&adoption_request_id=... |
Review one unknown execution and one exact future verification adoption |
| POST | /{request_id} |
Append the reviewed version 1 acknowledgement once |
| GET | /{request_id} |
Read that exact immutable receipt with current permissions and credential admission |
The strict UnknownCommandAcknowledgementV1 input contains the candidate, policy,
run, journal and execution digests, the exact followup object, and the server's
observed classification. Every input must acknowledge no original replay and
the bound verification and native continuation with literal true in
acknowledge_bound_verification_and_continuation. For start_unknown, it must also
acknowledge the unknown result and possible effects. For closed_before_start,
it must instead acknowledge that the complete native WAL has no start intent;
unknown-result acknowledgements do not apply. It accepts no claimed exit code,
success result or arbitrary absence proof.
This first contract covers native host executions under their original frozen
sandbox policy. Docker and pool custody require separate supported recovery.
The receipt leaves the original sandbox row, unknown start, consumed ordinal, held handoffs and all counters intact. It does not execute, adopt or resume. Only a later ordinary verification adoption using the bound request ID can admit the exact reviewed source, request, commands, policy, provider and new ordinals. Every handoff remains counted against the current finite policy. An exhausted window requires an explicit policy renewal and fresh review. Several eligible custody records require separate acknowledgements bound to the same future adoption. A receipt never waives unrelated or unreviewed executions. After every reviewed command has a known result (including known failures), only the completed handoff's factory response, native resume and continuation intent can carry the acknowledgement into coding, normal QA and Git. Existing frozen repair and provider grants remain required, with every spent counter retained. The acknowledging actor is checked again before dispatch and delivery. Original unknown outcomes remain unknown and are disclosed in publication communication.
The Python SDK exposes unknown_command_acknowledgement_candidate,
acknowledge_unknown_command and unknown_command_acknowledgement. After an
uncertain POST, read the original request identity; do not choose a new identity
or resend an unknown execution. See operator recovery.
A native factory administrator can review GET /runs/{id}/provider-recoveries/candidate?agent=codex or claude, explicitly POST the returned candidate digest under one caller-owned request ID to /runs/{id}/provider-recoveries, and read its exact receipt at /runs/{id}/provider-recoveries/{request_id}. Admission reserves one dispatch in the same run. It does not execute a model in the request or reset repair and verification budgets.
The strict body requires exactly one native process digest or explicit historical operator attestation. New-protocol unknown outcomes stay held. Current authority, source, provider and policy are checked again before launch, and all implementation intents count toward the four-dispatch limit. See failed official CLI recovery for the proof fields, provenance and lost-response procedure. This change exposes HTTP endpoints only.
The separate /runs/{id}/provider-recoveries/allowances surface reserves one fifth dispatch after a known native fourth-attempt failure. It requires a current native administrator with current execution authority. It accepts no historical process attestation or budget override.
| Method | Path | Purpose |
|---|---|---|
| GET | /runs/{id}/provider-recoveries/allowances/candidate?agent=codex&adopt_current_executable=true |
Review the exact eligible failure and selected executable |
| POST | /runs/{id}/provider-recoveries/allowances |
Reserve and consume the one lifetime final allowance |
| GET | /runs/{id}/provider-recoveries/allowances/{request_id} |
Read the exact receipt as the original current operator |
The strict POST body contains request_id (32 lowercase hexadecimal characters), candidate_digest, native_process_digest, mitigation_evidence_digest (each 64 lowercase hexadecimal characters), agent (codex or claude), adopt_current_executable (required literal true), and a nonblank reason of at most 2,000 characters. The mitigation digest is an administrator attestation, not server-generated QA evidence. HTTP201 retains a version-2 receipt with protocol native-provider-recovery-allowance-v1; the HTTP request does not execute inference.
Same ID, body and current operator return the existing receipt. A stale candidate, different request, revoked authority or spent allowance refuses without another reservation. A missing response never renews eligibility. Legacy recovery routes retain their existing schemas and four-dispatch limit; reading a final allowance through the legacy receipt route returns HTTP409 identifying the new endpoint. See the recovery procedure for launch checks, executable limits and lost-response handling.
Fifth-attempt worker feedback uses protocol: "native-provider-recovery-allowance-v1", literal attempt: 5, role_id: "implementer", task_id: "implement", allowance_id and allowance_digest, alongside the usual feedback fields. The native journal checks the actual consumed reservation and current authority before accepting it. Legacy WorkerFeedback remains limited to attempts 1–4.
These routes require a current native factory administrator and execution authority. They grant selected retained checks to one preallocated final recovery request; they do not reserve or execute the coding dispatch.
| Method | Path | Purpose |
|---|---|---|
| GET | /runs/{id}/coding-check-grants/candidate?recovery_request_id=ID&bind_port=0 |
Review the retained commands, runner, source/authority cut and remaining budget |
| POST | /runs/{id}/coding-check-grants |
Record the explicit grant once |
| GET | /runs/{id}/coding-check-grants/{request_id} |
Read the original grant or revocation receipt |
| GET | /runs/{id}/coding-check-grants/current |
Inspect current grant identity, revision, status, receipt fingerprint and expiry |
| POST | /runs/{id}/coding-check-grants/revocations |
Revoke the exact current grant revision |
The strict CodingCheckGrantInput rejects extra fields:
| Field | Required review |
|---|---|
request_id |
Grant request identity: 32 lowercase hexadecimal characters |
recovery_request_id |
Future final-allowance identity: 32 lowercase hexadecimal characters, retained before granting |
candidate_digest |
The candidate's opaque 64-character SHA-256 fingerprint |
expected_revision |
The candidate's nonnegative grant revision |
command_indices |
One to twenty distinct configured indices, each 0–19 and present in the candidate |
call_limit |
One to twenty invocations, no more than available interactive capacity; calls may repeat a selected index |
valid_seconds |
Lifetime of 30–3600 seconds, also enforced during invocation |
bind_port |
0 by default for automatic loopback selection, or a fixed port from 1024–65535 |
reason |
A nonblank explanation of at most 2,000 characters |
The candidate separates interactive_commands_remaining from independent_final_check_count. Configured and policy checks together remain subject to the existing final-verification limit of 20. Grant creation cannot reset that limit or the frozen shared runner budget.
The immutable grant receipt returns an opaque receipt_digest. Compare it with /current, along with grant ID, revision and expiry; do not recompute a native receipt hash from client-side JSON numbers. Only active current status can authorize the linked path. none, revoked and expired retain their distinct meanings, and an old receipt never overrides current permission or revocation checks.
A revocation request requires its own request_id, the exact grant_id, current positive expected_revision and a reason of 1–2,000 characters. Read that original request ID after an uncertain response. The active grant and revocation records remain in the WAL; revocation cannot erase prior effects.
After grant confirmation, refresh the final-allowance candidate and include coding_check_grant_id when reserving under the original recovery_request_id. Legacy CLI-only allowance bodies keep their existing wire shape. The scoped MCP tool accepts only command_index and its own 32-character request ID; it cannot choose a run, provider, directory, arguments, environment or timeout. See the recovery procedure.
| Method | Path | Operation |
|---|---|---|
| GET | /health |
Inspect server health |
| GET | /providers |
Read configured coding-provider readiness |
| GET | /openapi.json |
Read the authenticated OpenAPI contract |
| PUT | /providers/{id}/configuration |
Save write-only provider fields |
| POST | /providers/{id}/test |
Test configured access |
| GET | /skills, /policies, /workflow |
Inspect active policies and real stages |
| POST | /policies/sync |
Fetch a pinned data-only central catalog |
| GET | /profiles |
Read backend and frontend contracts |
| GET | /repositories |
List registered repositories |
| POST | /repositories |
Register a Git source |
| GET/PUT | /repositories/{id}/policies |
Read or select project policy IDs |
| GET | /runs |
List run history |
| POST | /runs |
Queue generation and verification |
| POST | /run-creation-requests/{request_id} |
Admit the exact retained run input once under its original identity |
| GET | /run-creation-requests/{request_id} |
Read the original immutable admission receipt |
| POST | /run-creation-requests/{request_id}/cancel |
Settle cancellation against a delayed original submission |
| GET | /run-creation-requests/{request_id}/decision |
Read the exact admitted or cancelled terminal decision |
| GET | /runs/{id} |
Read a run's events and evidence |
| GET | /runs/{id}/plan, /runs/{id}/journal |
Inspect durable tasks and receipts |
| GET | /runs/{id}/agent-checkpoints/candidates |
Discover bounded original-result references without continuing work |
| POST | /runs/{id}/agent-checkpoints/{completion_id}/restores |
Admit one reviewed original-result continuation |
| GET | /runs/{id}/agent-checkpoints/{completion_id}/restores/{request_id} |
Read that exact continuation ticket without dispatch |
| GET | /runs/{id}/execution-requests |
Read worker delivery and cancellation requests with their receipts |
| POST | /runs/{id}/execution-requests/{request_id}/reconcile |
Settle an unknown request only from matching recorded server evidence |
| POST | /runs/{id}/runner-continuations |
Admit one explicit continuation of the original eligible queued pool command |
| GET | /runs/{id}/runner-continuations/{request_id} |
Read that exact retained continuation without dispatching work |
| POST | /runs/{id}/resume, /runs/{id}/handoff |
Continue retained source; optionally select a new worker |
| GET | /deployment-targets |
List delivery targets |
| PUT | /deployment-targets/{id} |
Configure a delivery target |
| GET | /deployments |
List delivery records |
| POST | /runs/{id}/deploy |
Explicitly deploy verified source |
| POST | /deployments/{id}/rollback |
Run retained rollback commands and checks |
| GET | /scm/connections |
Read native application setup and status |
| PUT | /scm/connections/{provider} |
Save write-only native application settings |
| GET/PUT | /knowledge/configuration |
Read status or save write-only knowledge settings |
| POST | /knowledge/test, /knowledge/search |
Check scope or retrieve cited context |
| POST | /runs/{id}/knowledge/index, /runs/{id}/knowledge/remember |
Explicit verified-source admission or memory |
| POST | /runs/{id}/cancel |
Request cancellation |
| POST | /runs/{id}/retry |
Create another attempt after failure, cancellation or interruption |
| POST | /runs/{id}/publish |
Queue publication of an already verified local change |
| GET | /runs/{id}/artifacts/changes.zip |
Download retained changed files |
| GET | /learning/records/{id}/projection/observations/{request_id} |
Read the exact committed projection observation with current review access |
| GET/POST | /repositories/{id}/assistant/conversations/{conversation_id}/attachments |
List metadata or upload a conversation file |
| GET | /repositories/{id}/assistant/conversations/{conversation_id}/attachments/{attachment_id} |
Read scoped file metadata |
| GET | /repositories/{id}/assistant/conversations/{conversation_id}/attachments/{attachment_id}/content |
Download the original conversation file |
| GET | /repositories/{id}/assistant/conversations/{conversation_id}/capabilities |
Inspect the frozen model's image-input capability without inference |
| POST | /repositories/{id}/assistant/conversations/{conversation_id}/turns/{turn_id}/recover |
Fence an expired ownership epoch for explicit reconciliation |
The original-result recovery guide describes the checkpoint, intent and tagged result bindings required by the restore routes. Candidate discovery returns at most 16 saved implementation references and no model history or response body. Retain the original 32-character hexadecimal request ID before a restore POST; exact readback after an uncertain response never creates a replacement request.
The uncertain run-submission guide explains exact admission, cancellation and decision readback. The same enabled user can read or settle cancellation with current read access after signing in again. Replaying admission also requires the original authentication method and current execution authority.
ForgeClient exposes the same original-request and checkpoint contracts. Retain
the request ID and submitted input before calling a write method. These methods
use the client's existing authenticated identity; they do not choose another
identity, retry a request or fall back to legacy create_run.
| SDK method | HTTP operation |
|---|---|
request_run_creation(request_id, request) |
POST the original {"version": 1, "input": ...} envelope to /run-creation-requests/{request_id} |
run_creation_request(request_id) |
GET /run-creation-requests/{request_id} for the original admission receipt |
cancel_run_creation_request(request_id, request) |
POST the original version-1 digest and repository/project/component scope to /run-creation-requests/{request_id}/cancel |
run_creation_decision(request_id) |
GET /run-creation-requests/{request_id}/decision without submitting cancellation or admission |
agent_checkpoint_candidates(run_id) |
GET /runs/{run_id}/agent-checkpoints/candidates without continuing work |
request_agent_checkpoint_restore(run_id, completion_id, request) |
POST the explicitly reviewed restore input to /runs/{run_id}/agent-checkpoints/{completion_id}/restores |
agent_checkpoint_restore(run_id, completion_id, request_id) |
GET that exact restore ticket without dispatching another request |
Write methods accept the corresponding native RunCreationInput,
RunCreationCancelInput or RestoreInput model, or a dictionary validated by
that model. Run creation keeps omitted RunInput fields omitted, including
default policy selection; an explicit empty skills list remains explicit.
Request, run and restore IDs must be lowercase 32-character hexadecimal values;
the original completion ID retains its fbr1_ prefix.
Cancellation requires the retained request_digest, repository_id,
project_id and component_id; unassigned project/component fields are
explicitly null. Do not recompute the digest from current form edits. An
admitted cancellation decision identifies an already admitted run and does
not cancel that run.
Restore input contains the retained request_id,
expected_checkpoint_digest, expected_intent_digest and the selected tagged
source; it has no additional version field. An http_response source carries
its record_digest. A bridge_observation also carries its original
observation_id and terminal_digest. Discovery and readback do not select,
observe or consume a result on the caller's behalf.
HTTP errors retain the existing SDK RuntimeError behavior; transport errors
propagate from HTTPX. A missing result or uncertain response leaves the outcome
unresolved. Choose exact readback as a separate call, retaining the same IDs;
the SDK never generates a replacement ID or automatically resubmits. Successful
methods return the server's JSON dictionary without projecting or rewriting
receipt actor, input, scope or digest fields. They do not return raw HTTP bytes
or independently verify receipt cryptography.
The CLI and MCP tools below call those same SDK methods once under the caller's
existing authentication. Every ID is supplied by the caller; none is generated.
CLI write commands take a saved JSON object document, capped at 1 MB before the
native request validation. They preserve omitted input fields and explicit nulls.
MCP writes take the same native object in a required request argument.
CLI command (after forge) |
MCP tool | SDK method |
|---|---|---|
request-run-creation REQUEST_ID DOCUMENT |
request_run_creation(request_id, request) |
request_run_creation |
run-creation-request REQUEST_ID |
get_run_creation_request(request_id) |
run_creation_request |
cancel-run-creation-request REQUEST_ID DOCUMENT |
cancel_run_creation_request(request_id, request) |
cancel_run_creation_request |
run-creation-decision REQUEST_ID |
get_run_creation_decision(request_id) |
run_creation_decision |
agent-checkpoint-candidates RUN_ID |
get_agent_checkpoint_candidates(identifier) |
agent_checkpoint_candidates |
request-agent-checkpoint-restore RUN_ID COMPLETION_ID DOCUMENT |
request_agent_checkpoint_restore(identifier, completion_id, request) |
request_agent_checkpoint_restore |
agent-checkpoint-restore RUN_ID COMPLETION_ID REQUEST_ID |
get_agent_checkpoint_restore(identifier, completion_id, request_id) |
agent_checkpoint_restore |
Run and request IDs must be lowercase 32-character hexadecimal strings;
completion IDs must be fbr1_ followed by 32 lowercase hexadecimal characters.
The creation document is the exact {"version": 1, "input": ...} envelope.
Cancellation requires version 1, the original request_digest, repository_id,
and both project_id and component_id; use explicit nulls for both when no
project component applies. It settles delayed admission and does not cancel an
already admitted run. Reading its decision is always a separate read command.
The restore document contains its saved request_id, the two expected digests
and the selected tagged source described above, with no version field. Candidate
discovery never selects a source or requests restoration. Restore submission
can queue continuation; ticket acceptance does not prove execution success.
For example, submit a previously retained creation envelope, then choose exact readback as a separate action if the response is uncertain:
forge request-run-creation "$REQUEST_ID" saved-run-envelope.json
forge run-creation-request "$REQUEST_ID"
forge run-creation-decision "$REQUEST_ID"Neither surface automatically retries, reads after a write, allocates a
replacement ID, falls back to legacy run/create_run, observes a remote result,
or consumes a response. A 404 or transport failure leaves the outcome unresolved.
The four read tools advertise read-only, idempotent behavior; the three explicit
write tools conservatively advertise non-idempotent behavior to avoid prompting
automatic retries. Cancellation additionally advertises its destructive effect.
All seven descriptions are packaged native Agentic YAML templates. Existing
tools and their description bytes remain unchanged. CLI prints the returned JSON
and MCP returns its structured dictionary; neither preserves HTTP serialization
or independently verifies receipt cryptography. Local adapter tests establish
wire behavior, not live-provider or execution acceptance.
{
"name": "Meeting rooms",
"url": "https://github.com/your-org/meeting-rooms.git",
"provider": "github",
"default_branch": "main"
}Provider values are git, github, gitlab, bitbucket, azure and gitea.
Repository registration does not establish clone or publication permissions.
{
"repository_id": "the-id-returned-by-registration",
"brief": "Build the meeting-room reservation service described in our brief.",
"operation": "build",
"backend": "pyfly",
"frontend": "none",
"agent": "codex",
"commands": [{"argv": ["make", "check"], "timeout": 120}],
"publish": false
}Backend values are pyfly, larafly, java, rust and dotnet. Frontend values
are react, angular, nextjs, vue and none. Agent values include codex,
claude, agentic and bridge. Consult /profiles and /providers before
selecting a combination.
Commands require non-empty argument arrays and a timeout between 1 and 3600 seconds. Empty commands ask forge to discover verification from real project files. There must still be an executable verification gate.
A run response reports its ID and status. Poll /runs/{id} to obtain events,
verification, changed files, diff, artifacts, error details and any pull-request
URL. Do not infer success from HTTP acceptance of the queue request.
GET /api/v1/runs/{id}/worker-evidence?request_id=QUESTION_ID lists the raster previews retained for that exact question. Each record contains an opaque 64-character id, a bare filename, mime_type, byte count in bytes, and sha256. A question without recorded screenshots returns an empty list. This read does not generate images or reopen source-control files.
GET /api/v1/runs/{id}/worker-evidence/{image_id} returns only that retained image after current authentication, project/repository authorization and native journal checks. It returns Cache-Control: private, no-store, X-Content-Type-Options: nosniff and X-Content-SHA256. The body must match the listed MIME type, exact size and SHA-256. SVG, paths supplied by callers and public access tokens are unsupported. These endpoints are read-only; they do not answer the question or resume execution.
The SDK validates metadata, bounds streamed bytes and verifies the returned image before handing it to the caller:
images = client.worker_evidence(run_id, request_id)
if images:
image_bytes = client.worker_image(run_id, images[0])See answering an agent's question for roles, preview controls, waiting across restarts and answer reconciliation. Images remain worker evidence rather than a delivery approval.
Automatic repairs record an attempt number on each command result. The full
verification list preserves failed and successful attempts; final_verification
contains the checks supporting a successful run, and source_tree identifies
their source snapshot. Publication verifies that the workspace still matches
that snapshot. The operations guide explains the bounded repair
budget and data-directory and PostgreSQL schema ownership.
Invalid input is rejected; a rejected token requires correcting authentication.
Provider limits can pause a retained task; unfinished effects can require reconciliation. Inspect pause, display_status, plan and journal before continuing. Resume takes {}; handoff takes {"agent":"claude"} and captures new configured access. Retry creates a separate
attempt and preserves the failed result. Cancellation is a request to stop active
work, not a rollback of external effects.
Set FORGE_URL to the server origin and supply FORGE_API_TOKEN in the client
environment. The CLI uses the same authenticated API:
export FORGE_URL="http://127.0.0.1:8787"
uv run forge repository list
uv run forge run --repository REPOSITORY_ID --brief 'Build the reservation service.' \
--backend pyfly --frontend none --agent codex --check 'make check' --wait
uv run forge status RUN_ID
uv run forge export RUN_ID --output changes.zipforge doctor reads local provider and profile configuration. forge cancel,
forge retry and forge publish operate on the named run. Publication is an
explicit remote write; export writes a new local file and refuses an existing
output path.
import os
from firefly_forge.client import ForgeClient
from firefly_forge.models import Command, RunInput
with ForgeClient(os.environ["FORGE_URL"], os.environ["FORGE_API_TOKEN"]) as client:
repositories = client.repositories()
run = client.create_run(RunInput(
repository_id=repositories[0]["id"],
brief="Build the reservation service described in the product brief.",
backend="pyfly", frontend="none", agent="codex",
commands=[Command(argv=["make", "check"], timeout=120)],
publish=False,
))
print(run["id"], run["status"])Register at least one intended repository before using this example. Queueing a
run does not wait for completion; poll client.get_run(run["id"]) and inspect
verification before accepting the result.
GET /api/v1/projects/{project_id}/campaigns/{campaign_id}/report returns a deterministic local evidence snapshot for one campaign. It requires current project and repository read permissions. SDK project_campaign_report, CLI forge campaign report and MCP get_project_campaign_report use this same read route. See campaign evidence reports for states, exact task/checkpoint references, the digest contract and snapshot limits. The read performs no source-control refresh or execution.
forge mcp runs the standard MCP stdio transport. Configure your MCP client to
launch that executable with FORGE_URL and FORGE_API_TOKEN in its environment.
The tools list repositories, register a source, create a local run, inspect
evidence, cancel work and explicitly publish a verified run. MCP uses the same
authenticated API and its identity and project permission checks. Keep
publication within the authorized user's explicit intent.
For an eligible queued command after controller replacement, use the explicit runner continuation. Its request ID must be saved before submission. SDK, CLI and MCP do not retry an uncertain response. A completed continuation admission does not establish command success; inspect the original command and run receipts.
Provider configuration accepts {"values":{"model":"MODEL","api_key":"PRIVATE_KEY"},"clear_secrets":[]}. Field names vary by provider and are listed in /providers. Secret values are write-only; GET responses report presence. Empty secret fields retain a saved value; clear_secrets explicitly removes it. Queued runs retain an immutable private configuration revision.
Project policies accept {"skills":["implementation","verification","security"]}. Omitting skills when creating a run uses project defaults; an explicit empty array selects no optional policies. Core framework integration, source safety and verification cannot be disabled.
See connected accounts for typed service policy, client registration, browser consent and effect receipts; SCM for repository discovery, OAuth redirects and grants; knowledge for source selection and project scopes; and deployment for target commands, source checks and rollback requests.
When an observation response is lost, read its original request ID. This GET
reads the local immutable event; it does not contact flycanon, submit a source
or repeat the observation. A 404 means that exact request has no recorded
observation. Another request's verified projection does not establish success.
with ForgeClient(factory_url, access_token) as client:
receipt = client.learning_projection_observation_receipt(record_id, request_id)The same read is available as forge learning observation-receipt RECORD_ID --request-id REQUEST_ID and the MCP tool
get_learning_projection_observation_receipt(record_id, request_id). Each uses
the authenticated API and current project review permission. The MCP read is
marked read-only and idempotent.
The typed receipt separates the original event_state from
current_record_state and current_projection_state. New observations retain
the original actor, projection, submission request, workspace, target revision,
payload digest, content hash and citations. Historical fields that were never
recorded remain null; they are not reconstructed from today's projection.
A later credential registration can block readback of retained values. Neither
a missing receipt nor an unknown legacy field authorizes resubmission.
The projection status GET also exposes its authoritative payload_digest for
comparison with the original admitted envelope. Source observation checks the selected
source ID against current credentials before contacting flycanon, verifies the
returned source ID and indexed content, then checks the retained admission
identity again before recording the event. It does not claim that remote
indexing and the local transaction are atomic.
Use the development workflow guide for the project settings and receipt states. All routes require the authenticated factory actor and current project access.
| Method and route | Contract and effect |
|---|---|
GET /api/v1/projects/{project_id}/git-delivery-policy |
Read the saved policy, permissions and adapter capabilities. |
PUT /api/v1/projects/{project_id}/git-delivery-policy |
Validate GitDeliveryPolicyInputV1 and save the default using its expected previous digest. |
GET /api/v1/runs/{run_id}/git-deliveries |
Read GitDeliveriesViewV1 and its checkpoint receipts. |
POST /api/v1/runs/{run_id}/git-deliveries |
Validate GitDeliveryInputV1 and return 202 with a durable owning-worker ticket. |
GET /api/v1/runs/{run_id}/git-deliveries/requests/{request_id} |
Read the original ticket, result and event chain. |
GET /api/v1/runs/{run_id}/git-deliveries/observations/{request_id} |
Observe the exact retained intent and current state without repeating its effect. |
Configuration requires a current administrator with project membership-management authority. Remote delivery also requires release authority and an explicit draft-capable repository connection. The worker repeats the current run, lease, source and permission checks before Git effects. A request against an active worker or an unsettled earlier effect is refused. A new request ID cannot bypass an uncertain operation.
The 202 response acknowledges queue admission. Read the exact original ticket to establish whether the worker committed or published anything. Local commit, draft update, final verification and final publication remain separately recorded outcomes.
Flyquery is optional. Flycanon remains the required knowledge and memory service.
Install the analytics extra of the qualified Forge package to make the official
Flyquery 26.10.4 read SDK available. An unconfigured project does not import that SDK
or contact Flyquery.
An authenticated factory administrator binds one existing project to an HTTPS origin, tenant, workspace and dataset. The origin must use port 443 with a trusted certificate; custom ports and private CA configuration are unsupported in this SDK slice. Use a scoped Flyquery agent token with the upstream schema-read grant, not a user login token. Remote authorization still applies to every read.
| Method | Path under /api/v1/projects/{project}/analytics |
SDK method |
|---|---|---|
| GET/PUT | /configuration |
analytics_configuration / configure_analytics |
| GET | /catalog |
analytics_catalog |
| GET | /tables/{table} |
analytics_table |
| GET | /tables/{table}/objects/{object_id} |
analytics_schema_object |
| GET | /prepared/{query} |
Unavailable; refuses without contacting Flyquery |
Read configuration first. Use its exact revision as expected_revision when
saving; use zero only for the first binding. Every save supplies the complete
scope and write-only agent_token, including a save with enabled: false.
A conflicting revision is refused. There are at most 32 ordinary configuration
changes per project. An enabled revision 32 permits one final disable at revision
33, using expected_revision: 32, enabled: false, the unchanged endpoint, tenant,
workspace and dataset, and an explicitly supplied token. This terminal binding
cannot be edited or re-enabled. A connection already disabled at revision 32 has
no further changes. Disabling does not import the SDK or contact Flyquery. Each
committed change has an immutable native receipt. Credentials stay
in owner-private revision files, never in public configuration or native receipts.
configured means settings were saved; it does not mean remote access was tested.
In Studio, open Administration → Structured analytics and choose a project. A factory administrator can select Set up Flyquery or Edit connection:
- Confirm the existing Flyquery service, optional Forge analytics SDK and
workspace-scoped
flyquery.schema:readtoken are available. - Enter the HTTPS origin, tenant, workspace UUID and dataset UUID. Enter a token for this save; the form never loads a saved token. Clear the enable checkbox to disable reads, supplying the complete scope and token again. At revision 32, Disable connection locks the existing scope and permits only the terminal disable. Disabled revision 33 remains readable.
- Review the scope and expected revision, then select Save connection once. The browser clears the token on submission. A missing or inconsistent response leaves the save unconfirmed; explicitly reload the saved configuration before another save. Reloading is a current read, not proof that an earlier request can no longer settle. Revision checks still reject conflicting writes.
Project readers use Read catalog, choose a table to read its metadata, then optionally supply a known schema-object UUID. There is no automatic remote read, polling, retry or connection-test endpoint. Each browser request has a 15-second deadline; a browser timeout does not prove a save was rolled back. The explorer shows the observed scope, configuration revision, time and response digest. It does not list all fields or enable unavailable prepared-result and query features.
import os
from firefly_forge.client import ForgeClient
with ForgeClient(os.environ["FORGE_URL"], os.environ["FORGE_API_TOKEN"]) as forge:
project = os.environ["FORGE_PROJECT_ID"]
current = forge.analytics_configuration(project)
forge.configure_analytics(project, {
"expected_revision": current["revision"],
"enabled": True,
"endpoint": "https://analytics.example",
"tenant_id": "fictional",
"workspace_id": os.environ["FLYQUERY_WORKSPACE_ID"],
"dataset_id": os.environ["FLYQUERY_DATASET_ID"],
"agent_token": os.environ["FLYQUERY_AGENT_TOKEN"],
})
catalog = forge.analytics_catalog(project)Project readers can inspect the bound catalog and exact table/schema-object UUIDs. Browser headers cannot override the remote scope. Reads reject mixed scope, incomplete pages, changed configuration, revoked access and changed credentials. There is no retry or write fallback on 404 or transport failure.
The catalog is limited to 50 tables and one complete page. Exact schema lookup requires a known object UUID and its parent table's reported current snapshot; full table-field discovery is unavailable. Each response is limited to 256 KiB, with at most eight GETs and a ten-second remote deadline (three-second connect). Current operations use one GET, or two for an exact schema object. One read per project/actor is active in each API worker. Observations include the local response digest and observation time. Snapshot UUIDs are reported identity, not data-content hashes or a guarantee of a current atomic data cut.
Prepared results require a new upstream agent-token GET query-history/result API, exact tenant/workspace/dataset fencing and corresponding read SDK methods. The current user-tier query/result routes are not a substitute. No SQL, query generation, result download URL, model call, agent tool, CLI/MCP command or memory publication is added by these routes.