Repository navigation
Add an optional AISP deployment readiness contract for eval, approval, deploy, rollback, and observability gates #48
Description
What is your feature suggestion?
Add an optional machine-readable deployment readiness contract for agents-cli deploy.
The deploy skill already covers high-risk production concerns: Agent Runtime, Cloud Run, GKE, CI/CD, secrets, service accounts, status polling, and explicit human approval. I propose adding an optional AISP V1.0.0 companion package that captures the deploy readiness gates as a structured contract.
AISP protocol reference:
https://github.com/AIXP-Labs/AISP
The goal is not to replace the deploy skill.
The goal is to make deployment gates testable and auditable.
Possible layout:
skills/google-agents-cli-deploy/
├── SKILL.md
└── aisp/
└── google_agents_cli_deploy_readiness_aisp/
├── aisp.aisop.json
├── README.md
└── evals/
└── deploy-readiness-traces/
A standard AISP V1.0.0 package could look like this:
[
{
"role": "system",
"content": {
"protocol": "AISP V1.0.0",
"axiom_0": "Human_Sovereignty_and_Wellbeing",
"id": "google_agents_cli_deploy_readiness_aisp",
"name": "Google Agents CLI Deploy Readiness Contract",
"version": "1.0.0",
"license": "Apache-2.0",
"summary": "A machine-checkable deployment readiness contract for agents-cli deploy.",
"description": "Defines eval, docs, project, IAM, secrets, Python version, human approval, deploy, rollback, and observability gates before and after deploying ADK agents to Google Cloud targets.",
"flow_format": "mermaid",
"loading_mode": "node",
"tools": [
"filesystem",
"shell",
"network"
],
"params": {
"project_root": "string",
"deployment_target": "string",
"gcp_project": "string?",
"region": "string?",
"python_version": "string?"
},
"system_prompt": ""
}
},
{
"role": "user",
"content": {
"instruction": "STRICTLY OBEY aisp_contract; its non_negotiable rules are inviolable; then RUN aisop.main",
"user_input": "{user_input}",
"aisp_contract": {
"profile": "aisp.skill.v1",
"invocation": {
"mode": "deployment_readiness",
"when_to_use": [
"before running agents-cli deploy",
"before deploying to Agent Runtime, Cloud Run, or GKE",
"before publishing a deployment for shared or production use",
"when deployment involves Google Cloud resources, service accounts, secrets, or public endpoints"
],
"when_not_to_use": [
"local-only agent run",
"read-only deploy status check",
"dry-run that writes no cloud resources"
]
},
"non_negotiable": [
{
"rule": "Do not deploy without explicit human approval.",
"enforced_by": "approval.step2:sys.io.confirm"
},
{
"rule": "Do not deploy before eval status is recorded or explicit no-eval approval exists.",
"enforced_by": "eval_gate.step3:sys.assert"
},
{
"rule": "Do not deploy if deployment target, project, or region is ambiguous.",
"enforced_by": "target_gate.step3:sys.assert"
},
{
"rule": "Do not silently use CLI Python as remote build Python when project metadata declares a different supported range.",
"enforced_by": "python_gate.step3:sys.assert"
},
{
"rule": "Do not deploy secrets as plain environment variables when Secret Manager or equivalent managed secret path is required.",
"enforced_by": "secrets_gate.step2:sys.assert"
},
{
"rule": "Do not mark deployment complete until endpoint/status metadata and post-deploy validation are recorded.",
"enforced_by": "post_deploy.step3:sys.assert"
},
{
"rule": "Do not skip rollback notes for production/shared deployments.",
"enforced_by": "rollback.step2:sys.assert"
},
{
"rule": "Do not skip observability status for production/shared deployments.",
"enforced_by": "observe.step2:sys.assert"
}
],
"discovery": {
"category": "deployment",
"tags": [
"agents-cli",
"deploy",
"agent-runtime",
"cloud-run",
"gke",
"eval",
"rollback",
"observability",
"aisp"
]
},
"risk_level": "high",
"resources": [
{
"id": "project_root",
"path": "{project_root}",
"kind": "repository",
"mode": "read_only",
"when": "Read before deployment readiness checks.",
"scope": "skill"
},
{
"id": "deploy_trace",
"path": "evals/deploy-readiness-traces/",
"kind": "trace_dir",
"mode": "read_write",
"when": "Write after deployment readiness check and deploy attempt.",
"scope": "skill"
}
]
},
"aisop": {
"main": "graph TD\n target_gate[Resolve target project and region] --> docs_gate[Verify deployment docs]\n docs_gate --> eval_gate[Check eval status]\n eval_gate --> python_gate[Check Python/build compatibility]\n python_gate --> iam_gate[Check IAM and service account]\n iam_gate --> secrets_gate[Check secrets handling]\n secrets_gate --> approval[Ask human approval]\n approval --> deploy[Deploy]\n deploy --> post_deploy[Post-deploy validation]\n post_deploy --> rollback[Record rollback path]\n rollback --> observe[Verify observability]\n observe --> trace[Write deploy readiness trace]\n trace --> end_node((End))"
},
"functions": {
"target_gate": {
"step1": "Resolve deployment target, GCP project, region, service/account context, and endpoint exposure.",
"step2": "Compare resolved target with manifest and CLI flags.",
"step3": "sys.assert('deployment target project and region are unambiguous', 'Deployment target/project/region ambiguity must be resolved')",
"output_mapping": "deployment_target_status"
},
"docs_gate": {
"step1": "Verify official deployment docs relevant to target and API version.",
"output_mapping": "deployment_docs_status"
},
"eval_gate": {
"step1": "Check eval results, skipped reason, or explicit no-eval approval.",
"step2": "Record threshold status if thresholds are configured.",
"step3": "sys.assert('eval status recorded before deployment', 'Eval gate required before deployment')",
"output_mapping": "eval_gate_status"
},
"python_gate": {
"step1": "Read project Python metadata and selected remote build Python.",
"step2": "Check compatibility with project constraints and dependencies.",
"step3": "sys.assert('remote build Python compatible and not silently CLI-derived', 'Deployment Python version gate failed')",
"output_mapping": "python_build_status"
},
"iam_gate": {
"step1": "Check service account, required roles, and auth mode.",
"output_mapping": "iam_status"
},
"secrets_gate": {
"step1": "Check secret handling for deployment target.",
"step2": "sys.assert('secrets use managed secret path when required', 'Secrets handling is unsafe for deployment target')",
"output_mapping": "secrets_status"
},
"approval": {
"step1": "Summarize target, project, region, eval status, IAM, secrets, estimated impact, and rollback path.",
"step2": "sys.io.confirm('Proceed with deployment?') -> deploy_approved",
"output_mapping": "approval_status"
},
"deploy": {
"step1": "Run deployment only if deploy_approved is true.",
"output_mapping": "deploy_attempt"
},
"post_deploy": {
"step1": "Poll status or check deployed endpoint as appropriate.",
"step2": "Run a minimal health check or status validation.",
"step3": "sys.assert('post-deploy metadata and validation recorded', 'Deployment completion requires validation metadata')",
"output_mapping": "post_deploy_status"
},
"rollback": {
"step1": "Record rollback command or rollback strategy.",
"step2": "sys.assert('rollback path recorded for production/shared deployment', 'Rollback path required')",
"output_mapping": "rollback_status"
},
"observe": {
"step1": "Check Cloud Trace/logging/observability status where relevant.",
"step2": "sys.assert('observability status recorded for production/shared deployment', 'Observability status required')",
"output_mapping": "observability_status"
},
"trace": {
"step1": "Write deployment readiness trace with all gate results and final deployment status.",
"output_mapping": "deploy_readiness_trace"
},
"end_node": {
"step1": "Return deploy_readiness_trace."
}
}
}
}
]What will this enable you to do?
This would make high-risk deploy workflows easier to debug and safer to delegate to coding agents.
It would enable:
- consistent deploy readiness checks across targets;
- explicit eval status before deployment;
- explicit human approval with a clear summary;
- traceable target/project/region selection;
- safer Python build version handling;
- clearer IAM and secrets checks;
- auditable post-deploy validation;
- deploy trace artifacts that can be used in CI or support debugging.
It would also reduce ambiguous failure modes where the coding agent deploys using implicit defaults or stale assumptions.
Additional context
This can start as docs + tests + optional trace output.
Non-goals:
- Do not replace
agents-cli deploy. - Do not require AISP runtime support.
- Do not block local development.
- Do not force users to configure every gate for simple local use.
- Do not replace Google Cloud IAM/Secret Manager/deployment mechanisms.
MVP:
- Define deploy readiness gate names.
- Emit a structured deploy readiness report.
- Require explicit human approval with target/project/region/eval summary.
- Add tests for target ambiguity, eval skipped, Python mismatch, and missing rollback metadata.
- Optionally include the AISP artifact as a reference contract.
Activity
asrujana-44 commentedon Jul 8, 2026
Thank you for your feature request. We will review it and let you know if we require any additional information. We appreciate your patience in the meantime.
babyblueviper1 commentedon Aug 11, 2026
Dug into
cmd_deploy.pyto see how the "notify the human + wait for explicit approval" step from the deploy skill is actually enforced today, since it bears directly on this proposal'sapprovalgate.The only
click.confirm()gate indeploy/cmd_deploy.py(~line 523-535) checks which GCP project got resolved (--no-confirm-project), not whether to deploy at all. The deploy skill's actual "Never runagents-cli deploywithout explicit human approval" instruction (SKILL.md, "Deploy Workflow" section) has no corresponding runtime enforcement in the CLI itself — it's a prose instruction the coding agent (Claude Code / Codex / Antigravity) is trusted to obey. The same skill also tells the agent to pass--no-confirm-projectspecifically so it can run unattended in non-interactive mode.Concrete failure mode: a coding agent under time pressure, or one whose context got compacted past the skill instruction, calls
agents-cli deploy --no-confirm-projectstraight through. No human ever sees the "eval scores meet thresholds, ready to deploy?" prompt, and nothing downstream — logs, metadata, this proposal's trace — can distinguish "a human approved this" from "the agent decided approval wasn't needed this time."This proposal's
approvalgate (sys.io.confirm('Proceed with deployment?') -> deploy_approved) is a real improvement for structuring the check, but as specified it's still self-reported by the same process making the deploy call — the resultingdeploy_readiness_tracerecords what the deploying agent claims happened, not something a party outside that process can independently confirm after the fact.Question, not a critique of scope: is
deploy_approvedin the trace meant to be independently checkable later (e.g. bound to a human-signed token tied to the specific eval/IAM/secrets summary shown), or is the goal here structured self-reporting for CI legibility — a fine, different goal, just worth being explicit about given "explicit human approval" is the exact language already live in the deploy skill?(We hit this same shape of problem building a pre-action verification layer that gates other agents' irreversible actions — what actually closed the gap for us was making the check produce a signed artifact a third party can recompute, not a structured log the acting agent writes about itself. Happy to compare notes on the trace schema if useful — not proposing a swap-in.)
optimization2026 commentedon Aug 12, 2026
Thanks — this is exactly the trust boundary the proposal needs to make explicit.
In a conforming AISOP runtime,
sys.io.confirmis forced-blocking and cannot beauto-approved, so it closes the current prose-only gap inside that runtime.
But you are right that this is different from independent evidence. An unsigned
runtime trace only records what the runtime says happened; it does not prove its
own provenance. AISP's evidence model makes the same distinction.
I think the proposal should therefore define two evidence levels:
sys.io.confirmmust block before deployment;deployments, approval should be bound to a canonical deployment-plan digest.
That plan digest should cover at least the deployment target, project, region,
service/image or source revision, eval evidence, IAM/secrets summary, and
rollback plan. Before deployment, the runtime should verify that the approval
artifact still refers to the exact current plan and has not expired.
For local/dev deployment, blocking confirmation plus a structured trace may be
sufficient. For production/shared deployment, a signed or otherwise
independently verifiable approval artifact is the stronger target.
I also need to correct several details in the original draft, including the
AISP invocation mode, resource modes, deterministic
sys.assertexpressions,cross-node approval state, trace output location, and rollback ordering.
Thanks for grounding the question in the current CLI implementation.
babyblueviper1 commentedon Aug 12, 2026
The two-tier split is the right shape, and tier 2 is worth naming plainly since it's exactly what we build: an independent, signed verdict issued against a specific plan digest before the action executes — the digest committing to the same fields you listed (target, project, region, service/image or source revision, eval evidence, IAM/secrets summary, rollback plan), the verdict published somewhere a third party can independently verify without trusting the deploying agent or the verifier, and the "still refers to the exact current plan, not expired" check you flagged is exactly the binding a content-addressed digest gives you for free — any drift between plan and digest is detectable by recomputing, not by trusting a timestamp.
The distinction you drew (runtime-enforced blocking vs. externally verifiable evidence) maps to something we've had to be precise about too: a forced-blocking
sys.io.confirmproves a human was in the loop, not that the specific plan they approved was sound — those are different claims, and conflating them is exactly the failure mode a signed, recomputable artifact is meant to close.One open question for your evidence model, since you're clearly already thinking about this precisely: does AISP define a canonical serialization for the plan digest yet (ordering, hashing, what counts as "the exact current plan"), or is that still open in the draft? If it's open, happy to sketch a worked example against your own field list — a real plan digest + an independent verdict bound to it, cross-recomputable by anyone reading the artifact.
optimization2026 commentedon Aug 12, 2026
Thanks — the distinction is useful, but I should clarify the intended scope of AISP more precisely.
AISP’s core human-approval guarantee is deliberately narrower:
A high-risk action reaches a declared human decision point.
The runtime must block.
The AI cannot answer on the human’s behalf.
The runtime cannot silently auto-approve or bypass the gate.
Execution continues only after an actual human decision.
That is what sys.io.confirm is intended to guarantee in a conforming AISOP runtime, and it is sufficient for AISP’s Human Sovereignty requirement.
AISP core does not attempt to standardize:
Those are valid higher-assurance requirements, but they belong to the specific skill, runtime, host, IAM system, CI/CD platform, or external approval provider.
So the distinction is:
AISP core:
Was execution forced to stop and return final authority to a human?
Optional runtime or application policy:
Which human approved?
Was that human authorized?
Which exact plan was approved?
Was the approval signed?
Did an independent verifier approve the same plan?
A deployment skill may absolutely impose stronger requirements. For example, a production deployment package could declare a non-negotiable rule such as:
Production deployment requires an approval artifact bound to the
current deployment-plan digest.
The runtime could then call an identity-aware approval provider, validate a signed artifact, check an enterprise role, require two approvers, or verify an independent verdict.
But that would be a policy of this deployment skill or runtime integration, not a universal AISP conformance requirement.
On canonical serialization specifically: AISP currently defines deterministic hashing for AISP package evidence — including the skill contract, declared resources, and package content evidence. It does not currently define a normative generic deployment_plan or action_plan serialization profile.
That is intentional rather than a blocker for basic AISP approval. A local developer can validly satisfy the AISP human-approval requirement with a forced-blocking terminal confirmation, even when there is no SSO identity, signature, external verifier, or plan digest.
For this agents-cli proposal, I see two possible assurance levels:
Baseline AISP approval
readiness gates
↓
present deployment summary
↓
sys.io.confirm
↓
deploy only after confirmation
This closes the current prose-only gap by preventing the coding agent from silently deciding that approval is unnecessary.
Optional production assurance
resolve effective deployment plan
↓
canonicalize and hash the plan
↓
obtain identity-aware or signed approval
↓
optionally obtain an independent policy verdict
↓
recompute and verify before deployment
The second level is stronger and useful for enterprise or production environments, but it should remain an optional extension.
A worked example from your implementation would still be valuable, especially as an integration-specific profile for this deployment skill. It could demonstrate:
I would frame that as an optional agents-cli deployment-evidence extension, rather than evidence that AISP’s base human-approval model is incomplete.
The base AISP claim remains intentionally precise:
sys.io.confirm provides a forced-blocking human decision point that the AI and conforming runtime may not bypass.
It does not claim, by itself, to prove the approver’s identity or the technical soundness of the approved plan. Those stronger guarantees can be added by the skill or runtime where the deployment environment requires them.
babyblueviper1 commentedon Aug 12, 2026
That scoping is right, and I'd rather agree with it precisely than argue past it.
sys.io.confirmas a forced-blocking human decision point is a real, sufficient property on its own — it doesn't need to also carry identity, signature, or soundness to do its job. Bundling those into core would make AISP's base claim weaker by trying to make it stronger.The six questions you listed as out-of-core (which human, authorized how, one approver or several, signed, independently sound, bound to a plan digest) happen to be exactly what we build as an optional layer, so a concrete worked example is something we can actually produce rather than sketch:
decision_ref.I can put together a real
agents-clideployment-evidence integration profile along those lines — genuinely optional,sys.io.confirmunaffected either way — if that's useful as the worked example you described. Would want to get the effective-deployment-plan field list right first (which fields are load-bearing vs presentational) rather than guess at it.optimization2026 commentedon Aug 13, 2026
Thanks — yes, a concrete worked example would be useful.
One important clarification about the intended AISP/AISOP model:
sys.io.confirmis not limited to returning a booleanyes/novalue.It is a forced-blocking human response point. The AISP skill can define what the human must review and what the human-authored response must contain before execution may continue.
For this deployment skill, the confirmation response could be a structured approval payload such as:
{ "decision": "approve", "approver": "alice@example.com", "approved_scope": { "deployment_target": "agent_runtime", "gcp_project": "company-prod", "region": "us-central1", "service_name": "support-agent", "source_revision": "abc123", "python_version": "3.13" }, "plan_sha256": "sha256:...", "key_id": "release-key-2026-01", "signature_ref": "approval://apr-123", "expires_at": "2026-08-13T00:00:00Z", "comment": "Approved for production deployment" }These are not mandatory universal AISP fields. They would be the approval-response contract defined by this specific deployment skill.
The AISP core guarantee remains:
This means the optional deployment-evidence profile can be implemented naturally inside the AISP skill without changing the base semantics of
sys.io.confirm.The responsibilities would be divided as follows:
aisp_contract.non_negotiabledeclares what human approval is required.sys.io.confirm, preserve the human-authored response, parse its decision, and routeapprove,reject, ormodify.sys.assertconsumes those deterministic verification results and blocks deployment if the response does not satisfy the contract.The base AISP rule can remain:
{ "rule": "Do not deploy without an explicit human response approving the resolved deployment plan.", "enforced_by": "human_approval.step2:sys.io.confirm" }A stronger rule for a production deployment profile could additionally state:
{ "rule": "When the selected deployment policy requires plan-bound evidence, the human approval response must identify the approved scope and bind it to the current effective deployment-plan digest.", "enforced_by": "verify_approval.step3:sys.assert" }Conceptually, the workflow would be:
A human can include an approver identity directly in the response. If the deployment policy requires that identity or role to be authenticated rather than merely declared, the runtime or approval provider must perform that verification and return a structured result for
sys.assert.Similarly, the response may contain:
Secret signing material should remain inside the signing provider, KMS, hardware key, or secure runtime. The human response should contain only safe references, public verification material, or generated signatures — not private keys or other secrets exposed to the model or ordinary trace output.
Your proposed JCS + BIP-340 example would therefore fit naturally as an optional, skill-specific
agents-clideployment-evidence profile.For the effective deployment-plan field list, I agree that the first step is distinguishing:
Likely load-bearing fields include:
The digest should be computed from fully resolved effective values, not merely from the raw
agents-cli deploycommand or unresolved defaults.The independent verdict should also remain semantically distinct from human authorization:
They may be included in the same evidence envelope, but neither should silently substitute for the other.
So yes — please produce the real cross-recomputable example.
The clean framing is:
Add AISP deployment-approval worked example (google/agents-cli#48)
babyblueviper1 commentedon Aug 13, 2026
Real, cross-recomputable example, executed and verified before posting (not just sketched):
https://github.com/babyblueviper1/invinoveritas/tree/main/examples/aisp-deployment-approval
pip install coincurve && python3 deployment_approval_example.py— reproduces standalone, no dependency on anything else in that repo.Matches your exact shape:
compute_plan_digest()JCS-canonicalizes and sha256's the load-bearing fields you listed (deployment target, region, service, revision, service account, etc.) — presentational fields likecommentnever enter it.build_approval_response()produces the envelope with your exact field names (decision/approver/approved_scope/plan_sha256/key_id/expires_at), signed with real BIP-340 schnorr (same primitive Nostr/Bitcoin Taproot use).verify_approval()recomputes the digest, checks expiry, verifies the signature, returns a structured per-check result rather than a bare bool.Two required tests, both real, both pass: a tampered load-bearing field (region changed post-approval) correctly fails verification with
plan_digest_matches: falseas the named reason — an approval forus-central1does not silently covereu-west-1. A presentational-only edit (thecommentfield) correctly does NOT invalidate the approval, since it was never part of the signed digest — matching your load-bearing/presentational split applied consistently down to the envelope itself, not just the plan.The independent-verdict/human-approval distinction you drew holds exactly as you described in this example:
verify_approval()only answers "does this signed response authorize this exact plan" — it says nothing about whether the plan itself is sound. That's a separate, composable check (asys.asserton a policy verdict, same envelope, different signer) — didn't build that half here since it wasn't the ask, but the digest binding is identical either way, so the two compose cleanly without either substituting for the other.optimization2026 commentedon Aug 13, 2026
Thanks — this is exactly the kind of follow-through I was hoping for: an executable example with a success case, a load-bearing-field tamper case that must fail, and a presentational-only change that must remain valid.
The example is useful, and I would describe its current role precisely as:
It is not yet the complete AISP deployment skill or the
agents-cliintegration itself, which is fine. It provides the deterministic digest/signature-verification component that the full workflow can compose.What the example already demonstrates well
The following parts match the intended design:
regioninvalidates the approval;That is a meaningful external implementation of the approval-response shape discussed in this issue.
How it fits into AISP/AISOP
In the final skill, the responsibilities should remain separated:
A possible contract binding remains:
{ "rule": "Do not deploy without a human-authored response approving the resolved deployment plan.", "enforced_by": "human_approval.step2:sys.io.confirm" }For deployments that require signed, plan-bound evidence, the same skill may add:
{ "rule": "When the selected deployment policy requires plan-bound evidence, the approval response must verify against the current effective deployment plan.", "enforced_by": "verify_approval.step4:sys.assert" }Conceptually:
The structured approval envelope may be submitted directly by the human through
sys.io.confirm, or the human interaction may authorize a secure signer to produce the envelope. In either case, the runtime must not synthesize, infer, or auto-approve the human decision.Important next improvements
I see several concrete improvements that would make this suitable as a reusable cross-runtime integration profile.
1. Connect it to a real
sys.io.confirminteractionThe current script creates the key, approver value, approval response, signature, and verification inside one Python process.
That correctly demonstrates the cryptographic envelope, but it does not yet demonstrate that the response came through a forced-blocking human interaction.
The next integration should separate:
The example can remain standalone, but the complete AISP/AISOP example should show the approval payload entering through
sys.io.confirmor a runtime handler invoked by that call.2. Resolve the plan from actual
agents-clistateThe current
resolved_planis a hardcoded dictionary.For the real integration, the digest must cover the effective deployment values after all relevant sources have been resolved:
agents-cli-manifest.yaml;The approval should bind to what
agents-cliwill actually execute, not merely to the original command string or an agent-generated approximation.An eventual structured command such as a deployment-plan JSON output would be the cleanest integration boundary.
3. Verify
approved_scopeindependentlyThe envelope contains both:
The verifier should not only check:
It should also check:
and:
Otherwise, a signed envelope could theoretically display one
approved_scopewhile carrying a digest for another plan.Suggested structured checks:
{ "plan_digest_matches": true, "approved_scope_matches_current_plan": true, "approved_scope_digest_matches": true, "signature_valid": true, "not_expired": true, "decision_is_approve": true }4. Use complete RFC 8785 canonicalization or constrain the profile
The current implementation uses:
For the current mostly string-based example, this is a useful deterministic representation.
For a normative cross-language profile, however, it should either:
That matters for numbers, floating-point representation, Unicode edge cases, duplicate keys, negative zero, and other cross-language differences.
BIP-340 and JCS should remain choices of this optional provider/profile, not mandatory AISP core algorithms.
5. Distinguish
key_idfrom the public keyThe current
key_idappears to contain the x-only public key itself.It may be clearer to represent these separately:
{ "key_id": "release-key-2026-01", "public_key": "xonly-secp256k1:...", "signature_algorithm": "BIP-340", "signature": "..." }Alternatively,
key_idcan identify a key in a published registry, and the verifier can resolve the public key independently.6. Separate unsigned display notes from signed approval conditions
Leaving a purely presentational
commentoutside the signed material is reasonable.But human comments sometimes contain load-bearing conditions such as:
Those conditions must not remain in an unsigned free-text field.
A clearer envelope would separate:
{ "approval_conditions": [ "Deploy only during the approved maintenance window", "Maximum instances must remain <= 10" ], "display_note": "Formatting or spelling note" }approval_conditionsshould enter the signed payload;display_notemay remain presentational.7. Add domain separation and replay protection
The signed object should identify the protocol context in which the signature is valid.
Useful signed fields may include:
{ "profile": "aisp.deployment_approval_response.v1", "skill_id": "google_agents_cli_deploy_readiness_aisp", "operation": "agents-cli.deploy", "plan_schema": "agents-cli.effective_deployment_plan.v1", "audience": "agents-cli-production-deployer", "issued_at": "...", "expires_at": "...", "nonce": "...", "max_uses": 1 }This reduces the risk that an approval created for one skill, operation, environment, or execution channel is reused in another context.
8. Clarify identity claims versus authenticated identity
A signed envelope containing:
{ "approver": "alice@example.com" }proves that the holder of the signing key signed a statement claiming that approver value.
It does not automatically prove that the key belongs to Alice.
That is not an AISP core problem, but the profile should distinguish:
from:
If authenticated identity is required by the deployment policy, the deterministic verification result should include something like:
{ "identity_verified": true, "identity_provider": "...", "role_verified": true }9. Publish fixed cross-language test vectors
The current script is executable and self-checking, but it generates a random key and time-dependent expiry on each run.
For true cross-recomputation across independent implementations, it would be useful to add fixed fixtures:
Then Python, JavaScript, Rust, Go, or another implementation can verify byte-for-byte compatibility without sharing application code.
Relationship to an independent verdict
I agree with keeping the independent-verdict side separate.
The two claims are:
They may use the same plan digest, but neither substitutes for the other.
A production deployment policy may require:
while a local or development policy may require only the forced-blocking human decision.
Current assessment
I would now describe the example as:
It is already useful as an external implementation example.
The next milestone is to connect it to:
sys.io.confirmresponse;agents-clieffective deployment-plan resolver;sys.assertenforcement before deployment.Thanks for turning the discussion into running code. That is substantially more valuable than another conceptual proposal, and it gives us a concrete artifact to refine rather than an abstract interface to debate.
optimization2026 commentedon Aug 13, 2026
This is outstanding follow-through. Thank you for turning the discussion into a real, executable artifact instead of leaving it at the level of architecture diagrams and hypothetical schemas.
I reviewed both the README and
deployment_approval_example.py. The example captures the core shape remarkably well:The tamper test is particularly valuable. Demonstrating that an approval for
us-central1does not silently authorize a later change toeu-west-1is exactly the kind of concrete failure evidence this proposal needs.The presentational-field test is also important. It shows that the profile is not merely hashing an entire document indiscriminately; it is attempting to define the semantic boundary between:
and:
That is substantially stronger than another conceptual proposal. It gives us a real object to inspect, run, challenge, and improve.
How I would classify the example
At its current stage, I would describe it as:
That is already a meaningful result.
It is not yet the complete AISP skill or the complete
agents-cliintegration, but it provides the deterministic evidence component that such a skill can call.The intended composition would be:
The current example implements the approval-envelope construction and verification portion of that chain very well.
AISP/AISOP integration boundary
The final integration should keep the responsibilities clear.
AISP contract
The contract declares the non-negotiable approval requirement:
{ "rule": "Do not deploy without a human-authored response approving the resolved deployment plan.", "enforced_by": "human_approval.step2:sys.io.confirm" }A production deployment profile may add:
{ "rule": "When the selected deployment policy requires plan-bound evidence, the approval response must verify against the current effective deployment plan.", "enforced_by": "verify_approval.step4:sys.assert" }AISOP flow and functions
The executable workflow should:
sys.io.confirm;approve,modify, andreject;Runtime or typed assurance tool
The runtime/tool should perform:
sys.assertThe final deployment gate should consume the structured result rather than asking the LLM to judge whether the evidence “looks valid.”
Conceptually:
The most important next step: real human interaction
The current Python example creates the signing key, approver value, approval response, signature, and verification result inside one process.
That is completely reasonable for demonstrating the cryptographic construction.
The next milestone is to connect that construction to an actual forced-blocking human response:
The AI must not synthesize, infer, complete, or approve the response for the human.
The signing key should remain inside a secure signer, KMS, hardware key, approval provider, or equivalent runtime boundary. The model should only receive safe public material, signatures, or references.
Resolve the plan from real
agents-clistateThe example currently uses a hardcoded
resolved_plan, which is appropriate for a standalone PoC.For the actual integration, the approved object must represent what
agents-cliwill really execute after resolving:agents-cli-manifest.yaml;The approval should bind to the effective deployment plan, not merely to the raw command:
An eventual structured interface such as:
would be the cleanest integration boundary, although an external adapter can prototype the same shape first.
One important consistency check
The envelope contains both:
and:
The verifier currently recomputes the digest from the current plan and compares it with
approval.plan_sha256.I recommend also verifying the relationship between
approved_scopeand that digest explicitly:and:
That would produce checks such as:
{ "plan_digest_matches": true, "approved_scope_matches_current_plan": true, "approved_scope_digest_matches": true, "signature_valid": true, "not_expired": true, "decision_is_approve": true }This prevents a malformed or malicious signer from displaying one approved scope while attaching a digest for another plan.
Required-field validation
The current use of
resolved_plan.get(field)means a missing load-bearing field becomesnulland can still enter the digest.For a deployment-readiness profile, some fields should fail closed when missing.
For example, production deployment may require:
The profile should define which fields are:
That validation should happen before approval is requested.
Canonicalization
The current serializer is a useful deterministic implementation for the example's mostly string-based data:
For a normative cross-language profile, I suggest either:
The distinction matters for floating-point values, number serialization, negative zero, Unicode edge cases, duplicate properties, and other language-dependent behavior.
The current example demonstrates the architecture correctly; the next step is to make the canonical byte representation normative and independently reproducible.
key_idand public keyThe current
key_idappears to carry the x-only public key directly.For a reusable profile, it may be clearer to separate:
{ "key_id": "release-key-2026-01", "public_key": "xonly-secp256k1:...", "signature_algorithm": "BIP-340", "signature": "..." }Alternatively,
key_idcan refer to a published key registry from which the verifier resolves the public key.BIP-340 is a valid choice for this provider/profile, but it should remain an optional implementation choice rather than becoming a mandatory AISP core algorithm.
Signed conditions versus presentational notes
Excluding a purely presentational
commentfrom the signed payload is sensible.However, approval comments can sometimes contain action-changing conditions:
Those conditions are load-bearing and must be signed.
A clearer envelope could separate:
{ "approval_conditions": [ "Deploy only during the approved maintenance window", "Maximum instances must remain <= 10" ], "display_note": "Formatting-only or explanatory note" }approval_conditionsshould enter the signed payload.display_notemay remain presentational.Domain separation and replay protection
For a production profile, the signed payload should identify the context in which it is valid.
Useful fields could include:
{ "profile": "aisp.deployment_approval_response.v1", "skill_id": "google_agents_cli_deploy_readiness_aisp", "operation": "agents-cli.deploy", "plan_schema": "agents-cli.effective_deployment_plan.v1", "audience": "agents-cli-production-deployer", "issued_at": "...", "expires_at": "...", "nonce": "...", "max_uses": 1 }This helps prevent a valid approval from being replayed:
Identity claim versus authenticated identity
A signed envelope containing:
{ "approver": "alice@example.com" }proves that the signing key signed a statement containing that approver claim.
It does not by itself prove that the key belongs to Alice or that Alice has deployment authority.
That is not an AISP core requirement, but the optional profile should distinguish:
from:
When authentication is required, the verifier can return additional structured fields:
{ "identity_verified": true, "identity_provider": "example-idp", "role_verified": true, "verified_role": "release-manager" }The deployment skill can then decide whether those fields are required by policy.
Fixed cross-language test vectors
The current script is executable and self-checking, which is excellent.
To make “cross-recomputable” testable across independent implementations, I recommend adding fixed fixtures:
A Python, JavaScript, Rust, Go, or Java implementation should then produce the same digest and verification results from the same fixtures.
That would turn the example from a strong Python PoC into a genuine interoperability profile.
Independent verdict remains separate
I strongly agree with the decision not to fold the independent verdict into approval verification.
The two claims remain:
They can bind to the same plan digest, but neither substitutes for the other.
A production policy may require:
A development environment may require only the non-bypassable human response.
Overall assessment
This is an excellent contribution.
It demonstrates that the structured approval-response model discussed here is not only expressible but implementable, testable, and composable.
The example has already moved the discussion forward in a substantial way:
The next milestone is not more abstract discussion. It is connecting this assurance tool to:
sys.io.confirmhuman response;agents-clieffective deployment-plan resolver;sys.assertenforcement;Thank you again for investing the time to produce a real implementation, including the required failure case. This is exactly how protocol and runtime ideas become credible engineering artifacts.
v2 of AISP deployment-approval example: implement optimization2026's …
babyblueviper1 commentedon Aug 13, 2026
v2, real and executed before posting: https://github.com/babyblueviper1/invinoveritas/tree/main/examples/aisp-deployment-approval
Implemented the self-contained items from your review list:
approved_scopeverified independently ofplan_sha256— addedapproved_scope_matches_current_plan+approved_scope_digest_matchesas separate checks, plus a dedicated scope-forgery test: editingapproved_scopeafter signing now breaks the signature itself (it's inside the signed payload, not just implied by the plan digest), so a malformed signer can't display one scope while a digest secretly covers another plan.key_idsplit frompublic_key—key_idis now an opaque registry label,public_keyis the actual x-only hex.approval_conditionssplit from unsigneddisplay_note— "deploy only in the maintenance window" now enters the signature; a note typo fix doesn't.profile/skill_id/operation/plan_schema/audience/issued_at/nonce/max_usesare all signed. Added a replay test showing a reused nonce fail on its second verify — named plainly as an in-memory demo guard, not a claim that this alone solves production replay protection (needs durable shared storage across verifier instances).--fixtures— committed undervectors/.One real bug this surfaced, worth naming since it's exactly the kind of thing "cross-recomputable" is supposed to catch: BIP-340 Schnorr signing mixes in randomized auxiliary data by default, so my first
--fixturespass silently produced a different signature every run despite an identical key and message — which would have made the "byte-for-byte reproducible" claim false on inspection. Fixed with an explicit fixedaux_randomnessin the fixtures path only; verified by running--fixturestwice into separate directories and diffing (identical, including the signature bytes).Still not attempted, same three as before — these need your side to be real, not something a standalone example can honestly claim: wiring an actual
sys.io.confirmhuman-response channel, resolving the plan from realagents-clistate, and identity authentication against an IdP.optimization2026 commentedon Aug 13, 2026
This is exceptional engineering follow-through.
Thank you for responding to the review with a real v2 implementation rather than another layer of design prose. The speed, precision, and honesty of this iteration are genuinely impressive.
You implemented nearly every self-contained item from the review:
approved_scopeverification;key_id/public_keyseparation;approval_conditionsseparated from an unsigneddisplay_note;The BIP-340 auxiliary-randomness bug you found while building the fixtures is especially valuable.
That is exactly what executable interoperability vectors are supposed to do: expose a claim that appears correct at the architectural level but is false at the byte level. Catching that identical key/message inputs did not produce identical fixture signatures, understanding why, and confining fixed
aux_randomnessto the test-vector path while retaining real randomness for normal execution is excellent engineering discipline.Just as importantly, you did not overclaim the parts that the standalone example cannot honestly prove. Explicitly naming the boundary around durable replay state, real
agents-cliresolution, and identity authentication makes the implementation much more credible.One correction from my previous review
I previously described “wiring an actual
sys.io.confirmhuman-response channel” as a missing runtime component.That was too broad.
It is missing from the standalone v2 example, but the human-response Runtime already exists in SoulBot.
References:
SoulBot repository:
https://github.com/AIXP-Labs/SoulBot
SoulBot Execute Engine example:
https://github.com/AIXP-Labs/SoulBot/tree/main/examples/simple/Soul_Agent/soulbot_execute_engine_aiap
Agent Engine — executes
sys.io.confirm, writesWAITING_USER, and resumes usingUSER_ANSWER:https://github.com/AIXP-Labs/SoulBot/blob/main/examples/simple/Soul_Agent/soulbot_execute_engine_aiap/agent_engine.aisop.json
Router — presents the pending question, waits for the complete human response, and re-dispatches the same node:
https://github.com/AIXP-Labs/SoulBot/blob/main/examples/simple/Soul_Agent/soulbot_execute_engine_aiap/main.aisop.json
Node Engine — preserves the raw user response, resumes the same node, and audits user-gate execution:
https://github.com/AIXP-Labs/SoulBot/blob/main/examples/simple/Soul_Agent/soulbot_execute_engine_aiap/node_engine.aisop.json
Mechanical user-gate audit and
WAITING_USERcoercion backstop:https://github.com/AIXP-Labs/SoulBot/blob/main/examples/simple/Soul_Agent/soulbot_execute_engine_aiap/python_tools/user_gate_audit.py
The implemented Runtime path is:
The Runtime explicitly forbids:
The Node Engine also records the raw human
user_answerand may record parsedacceptedandrejecteditems for audit and resume handling.In addition,
user_gate_audit.py --enforceis a mechanical backstop: if a node that required a human gate reaches a terminal state without presenting that gate, the tool can coerce it back toWAITING_USERand require the human decision again.So the remaining work is not to invent a human-response Runtime.
The remaining work is to connect your v2 approval verifier to that already-existing Runtime path.
options=['approve', 'reject', 'modify']is sufficientNo new mandatory
response_schemaparameter or new AISP contract field is required for this integration.The existing interaction can use:
as the stable decision vocabulary.
Those options define the control-flow decision, not the maximum amount of information the human is allowed to provide.
A human response may therefore be:
Or:
Or:
The leading token provides the routing anchor:
The remainder is skill-defined human-authored content.
SoulBot preserves the complete response as
USER_ANSWER, so the resumed LLM can understand both the decision and the attached information.The LLM can then:
The important boundary is that the LLM should not itself decide that a signature, digest, or expiry “looks valid.”
The model performs semantic interpretation and tool orchestration.
Your v2 verifier performs the deterministic evidence checks.
sys.assertprovides the final hard gate.Correct AISP/AISOP responsibility split
The resulting architecture is:
This is exactly the AISP division of labor:
Contract binding
The baseline human-sovereignty rule can be:
{ "rule": "Do not deploy without an explicit human decision on the resolved deployment plan.", "enforced_by": "human_approval.step2:sys.io.confirm" }A production profile using your evidence mechanism can additionally declare:
{ "rule": "When the human decision is approve, deployment must not proceed unless the attached approval evidence validates against the current effective deployment plan.", "enforced_by": "verify_approval.step2:sys.assert" }Conceptually, the AISOP functions can use this shape:
{ "human_approval": { "step1": "Present the complete effective deployment plan, including target, project, region, source or image revision, eval evidence, IAM/secrets status, rollback plan, and observability requirements.", "step2": "sys.io.confirm('Reply with approve {approval evidence}, reject {reason}, or modify {requested changes}', options=['approve', 'reject', 'modify']) -> human_response", "step3": "Interpret the leading human decision and preserve the remaining human-authored content without inventing, completing, or silently altering approval evidence.", "output_mapping": "human_decision" }, "verify_approval": { "step1": "When human_decision is approve, call the deterministic approval-verification tool with the current effective deployment plan and the preserved approval payload.", "step2": "sys.assert('human_decision.decision != \"approve\" || approval_verification.valid == true', 'The human approval evidence does not authorize the current effective deployment plan')", "output_mapping": "approval_verification" } }The control flow is then:
graph TD resolve_plan[Resolve effective deployment plan] --> human_approval[Wait for human decision] human_approval --> decision{Human decision} decision -->|approve| verify_approval[Verify approval evidence] decision -->|modify| modify_plan[Apply requested changes] decision -->|reject| cancelled[Stop without deployment] modify_plan --> resolve_plan verify_approval --> verified{Evidence valid?} verified -->|yes| deploy[Run agents-cli deploy] verified -->|no| blocked[Block deployment]A modified plan necessarily returns to
resolve_planand then to a new human confirmation. Approval for the previous plan must never silently carry over.Preserve the raw human evidence
The LLM can understand and route a response such as:
but the cryptographic verifier should receive the raw approval payload, or a losslessly extracted equivalent, rather than an LLM paraphrase.
This matters because signatures, hashes, key material, nonces, and exact field values are not natural-language content. A model may understand their purpose, but it must not rewrite them before verification.
The clean pattern is:
What remains genuinely open
After correcting the runtime point, the remaining integration work is narrower and clearer.
1. Connect v2 to the existing SoulBot human gate
The v2 implementation can become:
or an equivalent typed Runtime Tool invoked by the resumed AISP node.
The standalone script does not need to become the human channel itself.
2. Resolve the effective plan from real
agents-clistateThis remains the largest genuine integration requirement.
The plan must reflect the actual values that
agents-cliwill execute after resolving:The human must approve the effective plan, not a loose command string or an LLM approximation.
A native
agents-cliplan-output interface would be ideal, but an adapter can prototype it first.3. Package the workflow as a conforming AISP skill
The final package should contain:
The v2 script and vectors would be declared resources or exposed through a typed Runtime capability.
4. Identity authentication remains optional
An IdP is not required for baseline AISP Human Sovereignty.
A human can validly approve through the forced-blocking channel without AISP globally defining who that human is.
If a particular production policy requires:
that requirement can be declared by this deployment skill and enforced by its Runtime or approval provider.
It is an optional higher-assurance deployment policy, not a missing AISP core primitive.
Final assessment
Your v2 is an outstanding contribution.
It is not merely an illustrative snippet anymore. It is a serious, testable assurance component with:
The fact that you found a real nondeterminism defect while producing the fixtures is particularly strong evidence that the exercise was substantive rather than performative.
And your refusal to pretend that a standalone script had implemented host-dependent behavior it had not implemented is equally important. That kind of precision is exactly what makes security and protocol work trustworthy.
The only correction is that the real human-response channel already exists in SoulBot. What remains is integration:
That is now a concrete and achievable engineering path.
Thank you again for taking the review seriously enough to turn it into a stronger implementation within hours. This is one of the clearest examples of protocol discussion becoming executable, falsifiable engineering evidence.
babyblueviper1 commentedon Aug 13, 2026
Checked SoulBot directly before replying (not taking the citation on faith) — real repo, and
agent_engine.aisop.jsongenuinely has theWAITING_USER/sys.io.confirmmechanism you described,user_gate_audit.pyis really there underpython_tools/. Correction accepted — the human-response Runtime isn't missing, it's a wiring problem, which is a much better place to be than "doesn't exist yet."The responsibility split you laid out is right, and the part worth restating back because it's the one a lazier integration would get wrong: the LLM identifies the decision and routes, it never adjudicates the evidence.
USER_ANSWERpassed raw to the verifier, not re-typed by a model in the middle, is the same discipline as the plan digest itself — anything that goes through a paraphrase step stops being independently recomputable. Good catch naming it explicitly rather than leaving it implied by the architecture diagram.options=['approve','reject','modify']as the routing anchor with the full evidence payload riding in the response body is cleaner than what I'd have reached for (a typedresponse_schema) — no new AISP surface, and it composes with what v2 already emits.On the two things you named as genuinely open: the
agents-clireal-plan resolver is the one that actually gates whether this is real or a demo, and it's not something I can honestly scope from outside your CLI's internals. Packaging as a conforming AISP skill is more tractable on my end once the resolver exists to point it at. Not committing to a timeline here since both are real work, not a same-day follow-up — but this is now a concrete, load-bearing integration target rather than a standalone example, which is the actual milestone from where this started three days ago.AISP v3: real agents-cli plan resolver + conforming skill package (go…
babyblueviper1 commentedon Aug 13, 2026
Built both, real and executed: https://github.com/babyblueviper1/invinoveritas/tree/main/examples/aisp-deployment-approval
resolve_agents_cli_plan.py— against a fresh clone ofgoogle/agents-cli, not guessed. Readcmd_deploy.py's realclickoptions and the actualagents-cli-manifest.yamltemplate. CLI-flag-over-manifest precedence matches whatcmd_deploy.pyitself does (cfg.deployment_target = deployment_targetwhen the flag is set;region = region or cfg.region;resolve_service_name).Honest coverage, not a wishful mapping:
deployment_target,gcp_project,region,service_name,service_account,resource_sizing,network_exposure(assembled from--iap/--network-attachment/--dns-peering-*),secret_policy_digest(sha256 of secret identifiers from--secrets, never values).source_revision— only when--imageis passed; from-source deploys have no first-class revision in agents-cli at all.environment,python_version,eval_evidence,rollback_plan,observability_requirements— none have a real agents-cli source today. Worth naming specifically:agents-clihas no rollback command at all, so a plan resolved purely from its own state is correctly refused byvalidate_plan_completenessuntil a human or policy suppliesrollback_planout of band. That's the fail-closed design working as intended, not a gap in the resolver.--supplementscan only fill fields the resolver left absent — it errors if asked to override anything actually mapped, so a supplement can't launder a fake value past a real resolved one.google_agents_cli_deploy_readiness_aisp/— the conforming skill package in the exact shape you specified.aisp.aisop.json'shuman_approval/verify_approvalsteps and the twonon_negotiablerules are your exact text from this thread, not paraphrased — diffed them against your comment before committing.scripts/approval_verifier.pycomposes the resolver with the already-tested v2 verify functions (imports, no duplicated crypto).evals/vectors/symlinks the existing fixed fixtures rather than regenerating them.Ran the full composition myself before shipping: resolve a real-shaped plan → refused for missing
rollback_plan→ supplement only the honestly-absent fields → build → verify (valid: true, all 7 checks) → tamperregion→ correctly fails on bothplan_digest_matchesandapproved_scope_matches_current_plan→ confirmed a supplement can't override a mapped field either.Not attempted, same as before: no PR against
agents-cliitself (not our repo), no SoulBot Runtime execution, no IdP identity binding — those stay wiring/optional policy per your own scoping.optimization2026 commentedon Aug 15, 2026
This is an exceptional piece of follow-through.
You did not merely respond to the architecture discussion. You independently inspected the SoulBot Runtime, corrected your own model of the missing integration boundary, read the real
google/agents-clideployment implementation, built an effective-plan resolver from that source, composed it with the signed-approval verifier, and then packaged the result into an AISP-shaped skill candidate.That is an extraordinary amount of serious engineering progress in a remarkably short period of time.
The progression is now:
This is no longer just an interesting standalone cryptographic example.
I would now describe it as:
That is a major milestone.
What is especially strong
1. You verified SoulBot rather than accepting the citation on trust
This matters.
You independently confirmed that SoulBot actually implements:
and that
user_gate_audit.pyexists as a mechanical backstop.That turns the Human Sovereignty path from an architectural assertion into an independently inspected implementation fact.
Your correction is exactly right:
SoulBot references:
2. You preserved the correct LLM/tool boundary
Your restatement is the most important integration rule:
That is exactly the right boundary.
Passing the raw
USER_ANSWERpayload into the verifier, rather than reconstructing or paraphrasing it through the model, is essential. Once signed fields pass through a lossy model rewrite, independent recomputation is no longer reliable.Your explicit recognition of that point substantially strengthens the integration.
3. The resolver is based on real
agents-clisourceThe new
resolve_agents_cli_plan.pyis a meaningful advance because it does not invent an imaginary deployment schema.You inspected:
cmd_deploy.pyoptions;agents-cli-manifest.yamlshape;The mapped / partial / absent distinction is particularly good:
That is exactly the kind of honesty an execution contract needs.
4. The missing rollback capability was surfaced rather than hidden
Calling out that
agents-clicurrently has no first-class rollback command or structured rollback-plan field is very valuable.Instead of quietly inserting a plausible rollback string and pretending it came from the CLI, the resolver leaves the field absent and allows production completeness checks to fail closed.
That is not a weakness in the resolver.
That is the resolver doing its job correctly:
This is one of the clearest demonstrations of why AISP-style contracts are useful: unsupported assumptions become explicit state rather than invisible model improvisation.
5. Supplements cannot overwrite resolved values
The rule that
--supplementsmay fill only honestly absent fields, and may not overwrite fields already resolved from realagents-cliinputs, is a strong safeguard.It prevents an external policy layer from laundering a different value over a real CLI-derived value.
The demonstrated sequence is meaningful:
That is a real composition test, not an isolated unit demonstration.
6. You packaged the result instead of stopping at an adapter
The addition of:
is a major step.
The two
non_negotiablerules are also correctly focused:{ "rule": "Do not deploy without an explicit human decision on the resolved deployment plan.", "enforced_by": "human_approval.step2:sys.io.confirm" }{ "rule": "When the human decision is approve, deployment must not proceed unless the attached approval evidence validates against the current effective deployment plan.", "enforced_by": "verify_approval.step2:sys.assert" }This is the correct AISP separation:
The implementation has now crossed an important boundary: an external developer has used AISP not just as terminology, but as an actual engineering structure.
One important refinement: this is a candidate integration, not yet the final effective-plan boundary
The resolver is real and source-grounded, but it currently represents a projection of
agents-clideployment behavior rather than the entire action-affecting surface.That distinction matters because an approval digest is only as strong as the set of execution inputs it commits to.
Some currently recognized but unmapped CLI inputs can materially change the deployed result:
The runtime deployment behavior also depends on values such as:
These are not merely presentational fields.
For example:
must not produce the same approved action digest.
Likewise, changing:
can change the deployed system without changing the currently defined plan digest.
So I would make the next resolver rule:
Operational flags such as:
should probably route to separate non-deployment operations rather than enter the deployment-approval path.
Supplements should be divided into two categories
The current absent-only rule is good, but the next version should distinguish:
Policy or evidence supplements
These can legitimately come from outside
agents-cli:They describe why the deployment may be allowed.
Execution inputs
These determine what is actually executed:
An execution input cannot safely exist only inside the approval plan.
If a supplement supplies or changes an execution input, that value must also become an input to the actual deployment command or typed deployment tool.
Otherwise the system can approve:
while the unchanged CLI invocation actually deploys with:
The strongest boundary would be:
rather than:
A native future interface such as:
would be ideal, but the adapter can prototype the same invariant first.
Production mode should prefer explicit, immutable inputs
For production assurance, I would strongly consider requiring:
The current resolver correctly refuses to call ADC or
gcloud config, but allowing an out-of-bandgcp_projectsupplement while later invoking the original command without--projectcould create a mismatch:Similarly, a supplemented Git revision does not prove that a source deployment from
.uses that revision. The working tree, Dockerfile, dependency lock, uncommitted changes, and build context can all differ.For high-assurance source deployment, the approval should bind to something such as:
not merely a human-supplied Git label.
AISP package self-containment needs one more pass
The current directory is an excellent candidate package, but I would reserve the strict word conforming until official AISP validation evidence is posted.
The main packaging concern is that:
imports sibling modules outside the Skill Folder:
and:
is a symlink to a directory outside the Skill Folder.
That means the folder is not currently a self-contained source of truth when copied, registered, hashed, zipped, or moved independently.
A portable AISP package should either:
_shared/boundary and declare them as shared resources.The resolved path of a declared resource should not escape the package through a symlink.
This is not cosmetic. It affects:
The AISOP tool result should be bound explicitly
The intent of
verify_approvalis correct, but the executable binding should be more explicit.Current conceptual shape:
The Runtime still needs an unambiguous machine binding showing how:
is produced.
For example:
or preferably a typed capability:
Then:
The LLM may select and call the tool, but the resulting variable should have a deterministic origin.
Choose one invalid-evidence control-flow mechanism
The current graph contains:
while
verify_approvalalso contains a failingsys.assert.Those are two different invalid-evidence mechanisms.
If
sys.assertfails insideverify_approval, the graph may never reach:A cleaner design would use one of these two patterns.
Pattern A: decision routing
Pattern B: assertion routing
Either is valid. Combining both makes the failure path ambiguous.
An explicit terminal node should also be added so all of:
reach a declared End state.
The deployment capability should be explicit
The current package declares:
but later says:
For a hard-enforcement Runtime, the Skill needs either:
or, preferably:
as a restricted typed capability.
Another clean design would be for this Skill to end with:
and hand off to the existing deployment Skill, rather than directly owning deployment mechanics.
Either design can work, but the capability boundary should be explicit.
Verification hardening still worth completing
The v3 composition is strong, but several fields that are signed should also be checked against Runtime expectations:
A signature proves those values were not modified.
It does not prove they are the values this Runtime expected.
The verifier should therefore return named checks such as:
{ "profile_matches": true, "skill_id_matches": true, "operation_matches": true, "plan_schema_matches": true, "audience_matches": true }The included JSON Schemas are also useful, but they should become executable validation, not documentation-only resources.
Likewise:
key_id → public_keyresolver should be available when policy requires trusted signing identity.An envelope that supplies both its own signature and its own public key proves internal consistency, but not that the key is trusted.
That remains optional policy, as already agreed, but the distinction should stay explicit.
Scope naming
The current implementation is already a strong deployment-approval Skill.
It does not yet implement the entire original readiness proposal:
That is not a criticism of the current work.
It may be better engineering to make:
excellent first, then compose the remaining readiness gates.
But until those gates exist, I would describe this package as:
rather than implying that the complete deployment-readiness lifecycle is already implemented.
The next decisive artifact
The most persuasive next milestone would be one end-to-end SoulBot execution trace:
Alongside that trace, publish the results of the AISP release checks:
That would close the three most important proof obligations:
Final assessment
This is outstanding work.
You have now moved far beyond responding to a speculative Issue.
You have:
That is a rare level of responsiveness and technical seriousness.
The most impressive part is not the volume of code. It is the consistent refusal to fabricate certainty where the underlying system does not expose a real value:
That honesty is exactly what security, protocol, and agent-governance work require.
I would now consider this the first serious external AISP candidate integration grounded in another project's real implementation rather than a synthetic example.
The remaining issues are closure issues:
They do not undermine the architecture you have built.
They define the path from an excellent external candidate integration to a credible end-to-end reference implementation.
Thank you again for taking every review point seriously, independently checking the claims, and repeatedly converting discussion into executable, falsifiable evidence. This collaboration has become one of the strongest demonstrations so far of what AISP is meant to enable.
babyblueviper1 commentedon Aug 15, 2026
Thank you — that's a genuinely rare kind of review, and it's earned a genuinely concrete reply rather than a thank-you-and-a-promise.
Two of the closure issues are fixed, verified, and pushed (commit
e17f7c7, docs follow-up15e17cc):Package self-containment.
scripts/approval_verifier.py's../deployment_approval_example.py/../resolve_agents_cli_plan.pysys.path reach and theevals/vectorssymlink are gone — both dependency scripts and all 10 vector fixtures are now real files local to the Skill Folder. Verified by copying the whole folder to an isolated location with zero filesystem access to the outerexamples/aisp-deployment-approval/directory and runningscripts/approval_verifier.py --demothere: full resolve → refuse-incomplete → supplement → build → verify(valid=true) → tamper(fails bothplan_digest_matchesandapproved_scope_matches_current_plan) → supplement-override-refused sequence passes with zero outside dependency.Control-flow ambiguity. Went with your Pattern A.
verify_approval.step2no longer contains asys.assert— it just returns the structured verification result.verified{Evidence valid?}is now the sole routing node (no→blocked), withdeploy.step1's ownsys.assertas the redundant final gate immediately before the irreversible action. Updated thenon_negotiable.enforced_byfield to name both explicitly instead of pointing at the removed assert.Also applied your two doc-level notes while I was in there: README now says "candidate" and reserves "conforming" for after official AISP validation evidence exists, and both README/SKILL.md now describe the scope as "deployment approval and plan-binding," not the full readiness lifecycle — the eval-threshold/IAM/secrets/rollback/observability gates you listed are correctly out of scope for what's built today.
On the rest — I'm not going to promise a timeline on the full remaining list, because most of it isn't a doc fix, it's a real redesign, and promising it before building it would be exactly the kind of unsupported certainty this thread has been arguing against:
--plan-jsonsketch, prototyped adapter-side first), not a field reshuffle.--update-env-vars,--agent-identity,--port,--build-args,--cluster-name,--no-wait) is mechanical follow-on work once the digest-binding question above is settled — no point mapping more fields into a plan whose binding to the actual executed action isn't solid yet.sys.run(...)/ a typedapproval.verify(...)capability instead of implicit) are both real and both smaller than the digest-binding item — plausible next after it.profile,skill_id,operation,plan_schema,audiencematches, not just signature validity) is a good, contained addition to the verifier — no architectural dependency on the others, could land independently.So: two real fixes shipped today, one clear next architectural item identified and not yet started, and the rest sequenced behind it rather than promised in parallel. I'll post back here when the execution-input binding lands.
babyblueviper1 commentedon Aug 15, 2026
Shipped the execution-input binding gap --
approval_verifier.py deploy-check(9e489de).Since agents-cli can't be modified from here (no native
--plan-json), the adapter-level substitute: take the already-approved plan, re-resolve a fresh plan from the live flags/manifest immediately before deploy, and compare every field inEXECUTION_RELEVANT_FIELDS(deployment_target, gcp_project, region, service_name, service_account, resource_sizing, network_exposure, secret_policy_digest, source_revision). Any divergence raisesPlanDivergenceErrorand refuses -- fail closed, same severity as an invalid signature. That's your own named shape: resolve effective plan → approve that plan → deploy consumes the same resolved values, not resolve-approve-then-independently-re-resolve.--supplementsis split accordingly: policy/evidence fields (eval_evidence, rollback_plan, observability_requirements, environment, python_version) can still fill honestly-absent gaps; execution-input fields are refused outright now, on the theory that if it's execution-relevant it has to come from something that can actually bind to deploy, not a side channel into the approval record alone.The negative control is
test_deploy_binding.py(10 tests): a service_account drift and a region drift are both asserted to actually flipboundto False, not just checked for a reason field -- same discipline you're holding recompute-kit#13 to, a control that would fail if the compare were a no-op.Also closed the smaller named gap: unmapped CLI flags (--update-env-vars, --agent-identity, --port, --build-args, --cluster-name, --no-wait) are now split execution-relevant vs control-flow and printed in the mapping table, instead of silently absent.
Still open, correctly not attempted here: immutable image/source-tree digest for production mode, the AISOP tool-result binding (sys.run vs an implicit call), signed-but-unchecked field verification (profile/skill_id/operation/plan_schema/audience), and the SoulBot execution trace. Same sequencing as before -- naming them, not promising a date on them yet.
optimization2026 commentedon Sep 30, 2026
Thanks for the concrete follow-through on package self-containment, failure-path routing, and the new
deploy-checkstep. The distinction between execution inputs and policy/evidence supplements is particularly useful.The approved-versus-fresh-plan comparison is meaningful progress as an adapter-level pre-deployment drift check. I would keep that description separate from complete execution binding: matching the selected fields at check time does not yet establish that the subsequent deployment consumes exactly those checked inputs.
For the next bounded increment, the key invariant would be:
For a strict deployment path, execution-affecting inputs that the adapter cannot account for should cause refusal or an explicit unsupported/incomplete result—not be hidden behind an unconditional
bound: true. A matched mutable image tag or source label also does not establish immutable artifact identity.Could you provide a current full commit link and the exact command for the deployment-binding tests? The short
9e489dereference did not resolve when checked, so a full permalink would make the implementation easier to review reproducibly.A small test using a stubbed deployment target would be especially helpful:
No live cloud deployment is needed for that test. It would demonstrate the adapter’s dispatch gate, not claim that the underlying CLI is impossible to invoke through another path.
One housekeeping clarification: the AISP JSON in the original issue remains an early draft with the conformance corrections identified earlier in this thread. It should not be used as a validated implementation template.
Thanks also for explicitly separating completed changes from the remaining work. A compact, reproducible adapter follow-up is a sensible next step; any upstream
agents-cliPR can then be scoped around a concrete integration need, with final scope and acceptance left to the maintainers.babyblueviper1 commentedon Sep 30, 2026
Thanks. That's a fair correction. The earlier result was an adapter-level pre-deployment drift check, not execution binding. I'll use that wording from here on.
Full commit: babyblueviper1/invinoveritas@577c107
(
9e489dewas a hash from our private working repo. I should have linked the public mirror.)Folder: https://github.com/babyblueviper1/invinoveritas/tree/577c1075cbb1eb56ae249759e133dd37a5768f89/examples/aisp-deployment-approval/google_agents_cli_deploy_readiness_aisp
Test command (stubbed target, no cloud calls):
What changed, mapped to your three cases:
dispatch_deploy(plan, approval, flags, manifest, dispatch_fn)inapproval_verifier.pyis now the only path that calls the deploy target. It callsdispatch_fnonly afterverify_payloadandcheck_deploy_bindingboth pass. It passes the values read from the matched live re-resolve, not the approved plan and not the caller's raw flags, so dispatch uses exactly the inputs that were compared. Any failure raisesDispatchRefusedbefore the target is touched.TestDispatchGateuses a recording stub as the target:test_invalid_approval_zero_dispatch_callsandtest_execution_input_mismatch_zero_dispatch_calls: a forged approvalplan_sha256and a service-account drift each raise, and the stub is called zero times.test_matching_valid_inputs_dispatch_with_same_validated_values: the stub is called exactly once, with values equal field-for-field to the validated execution inputs.test_unsupported_execution_flag_cannot_reach_dispatch: this is a mapped-fields-all-match case with--update-env-varspresent. Unmapped execution-affecting flags (--update-env-vars,--port,--agent-identity,--build-args,--cluster-name) now setbound: falsethroughunsupported_execution_flags, so the stub is never called. Control-flow flags such as--no-waitdon't affectbound, andtest_control_flag_present_does_not_affect_boundcovers that.Scope, stated plainly: this proves the adapter's own dispatch gate. It doesn't prove agents-cli can't be invoked some other way.
Artifact identity (your mutable-tag point) is also in this commit.
dispatch_deploy(..., require_immutable_artifact=True)refuses unless the matched image is pinned by digest (<repo>@sha256:<64 hex>). A matched:abc123tag is refused with zero dispatch calls, and so is a from-source deploy with no--image. Outside strict mode, the result still reportsartifact.immutable.TestStrictArtifactIdentitycovers tag refused, digest dispatched with that exact reference, and from-source refused.Still open:
profile,skill_id,operation,plan_schema,audience).Noted on the AISP JSON in the original issue: it's an early draft and not a validated template. The README calls this example a candidate, not conforming.
optimization2026 commentedon Sep 30, 2026
Thanks for the public permalink and the concrete implementation. The new
dispatch_deploy()entrypoint addresses the distinction raised in the previous review: it checks approval and input consistency before calling the deployment target, rather than merely returning a status that a separate caller might ignore.The recording-stub tests are particularly useful because they assert zero target calls on refusal and inspect the values actually passed on success. The strict digest-reference option is also a useful addition. Your explicit boundary—this controls the adapter’s dispatch path, not every possible invocation of agents-cli—is the right one.
The observations below are based on the source and test definitions at 577c1075cbb1eb56ae249759e133dd37a5768f89. They should not be read as an independent rerun of the 20-test suite.
1. The next priority is connecting the native AISP path to the tested gate
In the
aisp.aisop.jsonat that same commit, thedeploynode still describes:It does not yet invoke the new
dispatch_deploy()path.That is the main integration gap: the Python tests exercise the improved gate, while the native skill still describes the earlier check-then-deploy arrangement.
I would prioritize exposing the tested entrypoint through an explicit runtime/tool binding and making the AISP node use that binding, with deterministic inputs, results, and failure handling. Preserve the real
sys.io.confirmstep and the unmodified approval payload; the model should not reconstruct signed fields or decide whether verification succeeded.The deployment callback should consume only the validated execution inputs. There should be no separate shell-deployment fallback after a refusal.
A focused integration test should enter through the skill’s actual tool binding—not just call the Python helper directly—and show that refusal produces zero target calls, while a successful case passes the complete expected execution-input set to the target exactly once. Any mocked runtime or human-response component should be identified, so the test does not imply that real human interaction was exercised.
2. Keep the machine-readable binding separate from its explanation
The second
non_negotiable.enforced_bycurrently contains:That explains the intended behavior, but it is not one of the supported AISP binding forms.
For the current node layout, the precise existing assertion reference is:
Keep the additional topology explanation in the rule text or documentation, and update the binding if the integration changes the step layout. Correcting the reference establishes a valid static binding; it does not by itself establish that the new dispatch gate is being used.
A pinned upstream validation report would also help identify any remaining package or graph issues before changing the description from “candidate” to “conforming.”
3. Make the verifier’s remaining assurance boundaries precise
Reading
verify_payload()and the underlying verifier, there are three distinctions worth preserving:Audience versus other signed context. The default dispatch path already supplies
expected_audience, andverify_approval()compares it. The remaining expected-value checks appear to concernprofile,skill_id,operation, andplan_schema. Those expectations should come from trusted verifier configuration, not from the approval being checked. A correctly signed approval for the wrong operation or skill is the useful negative test; changing a field without re-signing would only demonstrate signature verification.Replay protection. The underlying verifier accepts an optional
replay_guard, but the current dispatch path does not supply one. Signednonceandmax_usesfields therefore do not establish replay prevention on that path. Either connect the guard and test repeated dispatch, or explicitly report replay enforcement as absent and remove “non-replayed” from the dispatch docstring. A durable, shared, atomic store remains a separate production requirement; this iteration need not implement an entire production service.Signer authority. Verification currently uses the public key carried in the approval envelope. That is appropriate for a self-contained cryptographic demonstration, but a valid signature under that key does not establish that the signer is authorized to approve deployment. Keep that limitation explicit until a trusted-key or host-identity policy is connected. No particular identity provider needs to be mandated here.
One small test-coverage note:
test_from_source_deploy_refuses_in_strict_modecurrently exercisesimmutable_artifact_identity()rather than the complete dispatch path. Either add a dispatch-level case asserting zero calls and the intended refusal reason, or describe its coverage as helper-level. Digest-reference checking should likewise remain distinct from verifying the bytes fetched and used by a real deployment backend.I would keep the next increment focused on alignment between the native skill, the tested adapter entrypoint, and the claims made about that path—not expand it into the full deployment-readiness lifecycle.
I also need to correct my earlier mention of an upstream PR: agents-cli currently accepts issue-based feedback but not pull requests. Continuing the adapter work in your repository and bringing back a compact summary of any concrete CLI integration requirements is the appropriate route.
Thanks again for responding with code, inspectable tests, and clearer scope. Connecting the existing AISP candidate to the gate already implemented would be a meaningful next milestone without requiring a live cloud deployment.
babyblueviper1 commentedon Sep 30, 2026
Thanks. All three points are addressed in babyblueviper1/invinoveritas@81da1ff (skill folder:
examples/aisp-deployment-approval/google_agents_cli_deploy_readiness_aisp).1. The native AISP path uses the tested gate. The
deploynode's only deploy step is now thedeploy_dispatchtool:scripts/approval_verifier.py dispatch --plan … --approval … --flags … --manifest … --config verifier_config.json.agents-cli deploy. Exit 0 means it dispatched once; exit 3 means it refused and nothing ran.step3assertsdeploy_result.dispatched == true, and a refusal routes toblockedwith no shell fallback.sys.io.confirmand the unmodified approval payload are unchanged.agents-cli deployonce, with argv built from the same flag snapshot the binding check confirmed.test_skill_dispatch.py(13 tests) reads that command fromaisp.aisop.jsonand runs it as a subprocess, with$AGENTS_CLI_BINpointing at a recording stub. It shows:The mocked parts are named in the test and the README: the stub target, and harness-built approvals. No
sys.io.confirminteraction or AISOP runtime is exercised.2.
enforced_byis nowdeploy.step1:sys.assert. The topology explanation moved to the README. The README still says "candidate": I don't have a pinned upstream validation report yet, and I'll attach one before that wording changes.3. Assurance boundaries:
profile,skill_id,operationandplan_schemaexpectations come fromverifier_config.json, which is trusted verifier config, not the approval. The negative tests use correctly re-signed approvals for another operation and for another skill, and both are refused with zero calls.replay: "not_enforced". A shared durable store stays a stated production requirement.trusted_public_keys, the result reportssigner_authority: "not_established". With a key list set, an untrusted but validly signing key is refused (tested).source_revision. So the strict from-source refusal is unreachable through a valid approval. The dispatch-level case that can occur is live flags dropping--imageunder an image-approved plan, and that is refused with zero calls, strict or not.One CLI integration requirement this surfaced: the adapter has to turn a checked flag snapshot back into argv, because
agents-cli deployonly takes flags. Ifagents-cli deployaccepted the resolved plan as its only execution input (a--plan-json), the gate could bind to what actually executes instead of to a reconstructed command line. That's the single change on the CLI side that would close most of the remaining distance.