client.proposals
client.proposals — the proposals operations.
On AsyncKindgi every method is the same, awaited.
client.proposals.list()
Section titled “client.proposals.list()”list( *, limit: int | None = None, cursor: str | None = None, status: Literal['draft', 'evaluating', 'evaluated', 'not-better', 'evaluation-failed', 'in-review', 'promoted', 'refused', 'rejected', 'expired', 'superseded', 'rolled-back', 'withdrawn'] | None = None, agent_id: str | UUID | None = None, tier: Literal['settings-block', 'prompt-block'] | None = None, scope_kind: Literal['tenant', 'org', 'project', 'segment'] | None = None, scope_id: str | UUID | None = None, segments: Sequence[ScopeSegment | Mapping[str, str]] | None = None, timeout: float | None = None,) -> FixProposalCollectionPageList improvement proposals. GET /v1/proposals
Newest first, cursor-paginated, only the proposals of agents the caller can read. Filters: ?agentId=, ?tier=, ?status= (statuses are derived, so a page filtered by status can hold fewer rows than limit), and the live scope a proposal is for (scopeKind, scopeId, segment, exactly as the promotions history takes it).
client.proposals.create()
Section titled “client.proposals.create()”create( body: CreateProposalBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> FixProposalPropose new content for a data block. POST /v1/proposals
A hand-written proposal: new settings values or a new prompt template for a block fromVersion pins, for a live scope. Checked as publishing that block version would be (its schema carries over), and refused when it equals the pinned content. The same change from the same version for the same scope is one proposal: answered 200 with X-Proposal-Deduped: true. Needs publish on the agent.
client.proposals.improve()
Section titled “client.proposals.improve()”improve( body: ImproveBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> ImprovementPassStart an improvement pass. POST /v1/proposals/improve
The runtime looks for better values for the version's tunable settings (keys its settings blocks' schemas mark x-kindgi-tunable) on the test set, within the budget, and writes its best candidate as an improvement proposal, which waits for a reviewer when requested. It answers at once with the pass, running. The pass works in one project, as an improve schedule does: projectId, else the scope's project, else (a tenant or org scope) the agent version's. The test set must be one that project reaches, and the pass's eval runs run there; its proposal's version is made where the agent's versions are. Checked first: the version is active and has something for the pass to work on (400 validation-failed, with details.reason): for a settings pass, a settings block with tunable keys (else no-tunable-keys), and for a prompt pass, instructions from a pinned prompt block (else no-pinned-prompt-block); the agent registry takes the versions a pass makes (409 registry-read-only; under kindgi dev, only for the whole tenant, since the pack's files serve every scope), and the agent has a live version for the whole tenant (409 proposal-needs-pin). No pass starts in a suspended project (409 project-suspended), and a pass going when it is ends cancelled, with the reason in cancelReason. Needs publish on the agent, and write on the pass's project when it isn't the version's. Without improvement passes in this runtime, 501 improve-unsupported.
client.proposals.improve_estimate()
Section titled “client.proposals.improve_estimate()”improve_estimate( body: ImproveBody | Mapping[str, Any] | None = None, /, *, timeout: float | None = None, **fields: Any,) -> ImprovementPassEstimateEstimate an improvement pass. POST /v1/proposals/improve/estimate
What a pass this input would start is estimated to cost, before you start it. The body is the start body of POST /v1/proposals/improve, resolved and reach-checked the same way: an unknown or inactive fromVersion (or the version serving the scope) answers 404 agent-version-not-found, and a test set or scope the pass's project doesn't reach answers 400 reference-out-of-scope, exactly as improve would. estimatedCostUsd is min(budget.maxCostUsd, the replay count times the version's mean cost over its recent completed runs) — clamped to the budget cap — and is absent when the version has no cost history; basis gives the unclamped inputs: the replay count, and that mean when there is one. The estimate prices every replay at that one mean, so a candidate whose prompt or settings cost more or less per run isn't captured, and the estimate leaves out a prompt pass's one-off drafting of its templates — a pass can cost more than the estimate. Because estimatedCostUsd is clamped to budget.maxCostUsd, an estimate at the cap means the pass is expected to spend its whole budget; the pass checks its cost before each comparison, so the one already running can take it a little over, and it starts no more once the cost reaches budget.maxCostUsd. It changes nothing (no pass starts) and takes no Idempotency-Key. Needs publish on the agent, and write on the pass's project when it isn't the version's. Without improvement passes in this runtime, 501 improve-unsupported.
client.proposals.get()
Section titled “client.proposals.get()”get(proposal_id: str | UUID, /, *, timeout: float | None = None) -> FixProposalFetch an improvement proposal. GET /v1/proposals/{proposalId}
Needs read on its agent.
client.proposals.evaluate()
Section titled “client.proposals.evaluate()”evaluate( proposal_id: str | UUID, body: EvaluateProposalBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> FixProposalCompare a proposal on a test set. POST /v1/proposals/{proposalId}/evaluate
The first evaluation publishes the block version and derives the agent version (derivedFrom.proposalId); they serve no scope until a promotion makes them live. Then a comparison eval run replays that version on the test set, against the recorded outputs (baseline: 'recorded'). Needs publish on the agent, and a live version of it for the whole tenant: an agent with none serves its latest version wherever nothing is pinned, so a new version would go live there at once (409 proposal-needs-pin). Allowed from draft, evaluated, not-better, evaluation-failed, refused, superseded and expired.
client.proposals.rescore()
Section titled “client.proposals.rescore()”rescore( proposal_id: str | UUID, /, *, idempotency_key: str | None = None, timeout: float | None = None,) -> FixProposalRescore a proposal's latest evaluation. POST /v1/proposals/{proposalId}/rescore
After people judge a comparison's new answers on its replay runs (perCase[].changes.new, runIds), a new comparison eval run scores the same replays again, counting those judgments, as POST /v1/eval-runs/{runId}/rescore does: same test set version and settings, comparison.rescoreOf, nothing replayed. It becomes the proposal's evaluation, so the proposal is evaluating, then evaluated or not-better as the rescore says; the run rescored stays as it was. Takes no body fields. Needs publish on the agent. Allowed from evaluated, not-better, refused, superseded and expired.
client.proposals.request()
Section titled “client.proposals.request()”request( proposal_id: str | UUID, body: ProposalReasonBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> FixProposalRequest a proposal's promotion for its scope. POST /v1/proposals/{proposalId}/request
A promotion of the candidate for the proposal's scope, with its evaluation's comparison, through the scope's gate: as POST /v1/agents/{agentId}/promotions answers. Needs promote on the agent. Allowed from evaluated, not-better (the gate decides), refused, superseded and expired.
client.proposals.rollback()
Section titled “client.proposals.rollback()”rollback( proposal_id: str | UUID, body: ProposalReasonBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> FixProposalRoll back a promoted proposal. POST /v1/proposals/{proposalId}/rollback
The scope goes back to the version its own pin held before the proposal's promotion (or, with none, falls back to the scope above). Only while the proposal's version still serves the scope. Needs promote on the agent.
client.proposals.withdraw()
Section titled “client.proposals.withdraw()”withdraw( proposal_id: str | UUID, body: WithdrawProposalBody | Mapping[str, Any] | None = None, /, *, idempotency_key: str | None = None, timeout: float | None = None, **fields: Any,) -> FixProposalWithdraw a proposal. POST /v1/proposals/{proposalId}/withdraw
Closes it. Not while it's in review (decide its approval instead), nor once promoted, rejected or rolled back. Needs publish on the agent.
client.proposals.draft()
Section titled “client.proposals.draft()”draft(*args: Any, **kwargs: Any) -> NoReturnRemoved in 0.1.5: use client.proposals.create.
client.proposals.dry_run()
Section titled “client.proposals.dry_run()”dry_run(*args: Any, **kwargs: Any) -> NoReturnRemoved in 0.1.5: use client.proposals.evaluate.
client.proposals.submit_review()
Section titled “client.proposals.submit_review()”submit_review(*args: Any, **kwargs: Any) -> NoReturnRemoved in 0.1.5: use client.proposals.request.
client.proposals.apply()
Section titled “client.proposals.apply()”apply(*args: Any, **kwargs: Any) -> NoReturnRemoved in 0.1.5: use client.proposals.request.