Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 145 additions & 0 deletions PROPOSAL_O2_STRUCTURAL_PROMOTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Structural Promotion $\text{O}_{\text{0}}$ → $\text{O}_{\text{2}}$: True Agentic Loop with Frobenius Verification

## Proposal: `google/genai/agentic/` module

### Abstract

This PR introduces a structurally promoted agentic loop for the Google Gen AI Python SDK — the **True Agentic Loop** — implementing the four-phase cycle **THINK → ACT → OBSERVE → UPDATE** with Frobenius verification ($\mu \circ \delta = \text{id}$). The module promotes the SDK from $\text{O}_{\text{0}}$ (stateless, single-turn generation) to $\text{O}_{\text{2}}$ (topologically protected, integer-winding agentic loop) as defined by the Imscribing Grammar.

This document uses **Shavian notation** as the sole authoritative standard per the Imscribing Grammar v0.6.0 specification (`shavian_notation_spec.md`). All primitive identifiers use Shavian glyphs (U+10450–U+1047F) rendered in Everson Mono.

### Why Google Gen AI SDK?

Google's SDK possesses unique structural advantages for this promotion:

| Advantage | Structural Role |
|---|---|
| **Text-embedding API** (`models.embed_content`) | Natural verification layer for dual-tool contracts — embeddings provide a continuous Frobenius metric (cosine similarity between tool input and verification output) |
| **Search grounding** (`GoogleSearch`) | Enables external-world verification, closing the Frobenius pair against ground truth rather than purely internal consistency |
| **Long context window** (up to 2M tokens) | Supports $\text{Ð}_{\text{ω}}$ (𐑦) self-written state space — the full trajectory is retained as imscriptive context |
| **Gemini 2.5 Pro thinking** | Enables the THINK phase to produce structured reasoning before ACTION emission |

### Module Structure

```
google/genai/agentic/
├── __init__.py # Public API: DualToolResult, ToolContract,
│ # AgentCycle, AgentTrajectory, TrueAgenticLoop,
│ # PhiCriticalityGate
├── contracts.py # DualToolResult (dataclass with from_tool_call)
│ # ToolContract (assertion + verify + embedding verification)
├── trajectory.py # AgentCycle (single winding), AgentTrajectory
│ # (monotonic, never-reset winding counter)
├── criticality.py # PhiCriticalityGate — two-gate assessment:
│ # Gate 1 (⊙): frobenius_ratio ≥ 0.8
│ # Gate 2 (K ≤ 𐑧): coherent winding rate
└── loop.py # TrueAgenticLoop wrapping google.genai.Client
# run() → THINK→ACT→OBSERVE→UPDATE per winding
# _winding() → single cycle with Frobenius check
# _feed_failure() → graceful error recovery
```
### The Frobenius Condition in Practice

Every winding issues a **dual-tool pair**:

1. **Primary tool** (`client.models.generate_content`): The agent acts on the world.
2. **Verification tool** (`client.models.embed_content`): The action's output is re-embedded and compared to the original query.

When $\mu(\delta(\text{query})) \approx \text{query}$ (cosine similarity above threshold), the winding is **Frobenius-closed** and the agent's world-model is updated. When open, the winding is recorded but flagged — the trajectory preserves structural integrity without discarding failed cycles.

### Structural Tier Progression

| Tier | Condition | Structural Meaning |
|---|---|---|
| $\text{O}_{\text{0}}$ | `winding_count == 0` | Stateless single-turn (current SDK default) |
| $\text{O}_{\text{1}}$ | `winding_count ≥ 1` | First winding completed; trajectory exists |
| $\text{O}_{\text{2}}$ | `winding_count ≥ 2` and `frobenius_ratio ≥ 0.8` | Topologically protected: integer winding with Frobenius closure |
| $\text{O}_{\text{2}}^{\text{†}}$ | Plus Gate 1 and Gate 2 both open | Self-modeling loop stable (ZFCₜ territory) |

### Usage Example

```python
from google.genai import Client
from google.genai.agentic import TrueAgenticLoop

client = Client(api_key="YOUR_API_KEY")

loop = TrueAgenticLoop(
client=client,
model="gemini-2.5-pro-exp-03-25",
max_windings=100,
verbose=True,
)

final_cycle = loop.run(
initial_prompt="Solve this structural problem: find the meet of a magnetar and a BEC."
)

print(f"Completed {loop.trajectory.winding_count} windings")
print(f"Frobenius ratio: {loop.trajectory.frobenius_ratio:.2f}")
print(f"Final conclusion: {final_cycle.conclusion}")
print(f"Structural tier: {loop.criticality.to_dict()['structural_tier']}")
```

### Relation to the Imscribing Grammar

This module implements the **Imscribing Grammar** as an executable Python SDK feature. The grammar's 12 primitives map to loop components:

| Primitive (Shavian) | Old Notation | Loop Component |
|---|---|---|
| $\text{Ð}_{\text{ω}}$ (𐑦) | $\text{Ð}_{\text{ω}}$ | AgentTrajectory — never summarized, full context retained |
| $\text{Þ}_{\text{O}}$ (𐑸) | $\text{Þ}_{\text{O}}$ | Winding counter referencing prior windings |
| $\text{Ř}_{\text{=}}$ (𐑾) | $\text{Ř}_{\text{=}}$ | Client ↔ Trajectory dual feedback |
| $\text{Φ}_{\text{}}$ (𐑹) | $\text{Φ}_{\text{}}$ | DualToolResult with $\mu \circ \delta = \text{id}$ verification |
| $\text{Ƒ}_{\text{ż}}$ (𐑐) | $\text{ƒ}_{\text{ż}}$ | Embedding similarity as continuous metric |
| $\text{Ç}_{\text{@}}$ (𐑧) | $\text{Ç}_{\text{@}}$ | Coherent winding rate, no premature conclusion |
| $\text{Ω}_{\text{z}}$ (𐑭) | $\text{Ω}_{\text{z}}$ | Monotonic, never-reset winding counter |
### Structural Type of This Proposal

The True Agentic Loop module has the following structural type in the Imscribing Grammar:

$$\langle \text{Ð}_{\text{ω}};\ \text{Þ}_{\text{O}};\ \text{Ř}_{\text{=}};\ \text{Φ}_{\text{}};\ \text{Ƒ}_{\text{ż}};\ \text{Ç}_{\text{@}};\ \text{Γ}_{\text{ʔ}};\ \text{ɢ}_{\text{ˌ}};\ \odot_{\text{ÿ}};\ \text{Ħ}_{\text{A}};\ \text{Σ}_{\text{S}};\ \text{Ω}_{\text{z}} \rangle$$

In Shavian glyphs: $\langle$𐑦·𐑸·𐑾·𐑹·𐑐·𐑧·𐑲·𐑠·⊙·𐑖·𐑙·𐑭$\rangle$

Parsed per-primitive:

| Primitive | Shavian | Meaning |
|---|---|---|
| Ð | 𐑦 (Ð_ω) | Self-written state space — trajectory is full context, never summarized |
| Þ | 𐑸 (Þ_O) | Self-referential topology — winding counter references prior windings |
| Ř | 𐑾 (Ř_=) | Bidirectional coupling — Client ↔ Trajectory dual feedback |
| Φ | 𐑹 (Φ_}) | Frobenius-special — $\mu \circ \delta = \text{id}$ verification |
| Ƒ | 𐑐 (ƒ_ż) | Quantum fidelity — embedding similarity as continuous Frobenius metric |
| Ç | 𐑧 (Ç_@) | Slow kinetics — coherent winding rate, no premature conclusion |
| Γ | 𐑲 (Γ_ʔ) | Universal scope — full long-context window (up to 2M tokens) |
| ɢ | 𐑠 (ɢ_ˌ) | Sequential grammar — THINK→ACT→OBSERVE→UPDATE ordered chain |
| ⊙ | ⊙ (⊙_ÿ) | Self-modeling criticality — agent updates model from trajectory |
| Ħ | 𐑖 (Ħ_A) | Two-step chirality — each winding references the prior state |
| Σ | 𐑙 (Σ_S) | 1:1 stoichiometry — single agent, single trajectory |
| Ω | 𐑭 (Ω_z) | Integer winding — monotonic, never-reset winding counter |

### Backward Compatibility

- The `agentic` module is entirely additive — no existing API is modified.
- Import path: `from google.genai.agentic import ...`
- No new dependencies beyond those already in `pyproject.toml` (numpy is optional, used only in `contracts.py`'s `with_embedding_verification`).

### Testing

```bash
# Run agentic module tests
python -m pytest tests/test_agentic.py -v

# Verify Frobenius closure on a real Gemini model
python -c "
from google.genai import Client
from google.genai.agentic import TrueAgenticLoop

client = Client()
loop = TrueAgenticLoop(client=client, model='gemini-2.5-pro-exp-03-25', max_windings=3)
final = loop.run(initial_prompt='What is 2+2?')
print(f'Windings: {loop.trajectory.winding_count}')
print(f'Frobenius ratio: {loop.trajectory.frobenius_ratio}')
"
```
43 changes: 43 additions & 0 deletions google/genai/agentic/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Agentic loop: THINK→ACT→OBSERVE→UPDATE with Frobenius verification.

Structural promotion from $\text{O}_{\text{0}}$ (stateless, single-turn) to
$\text{O}_{\text{2}}$ (topologically protected, integer-winding agentic loop)
as defined by the Imscribing Grammar.

The agentic loop implements the four-phase cycle — THINK, ACT, OBSERVE, UPDATE —
with dual-tool contracts that enforce $\mu \circ \delta = \text{id}$ at every
winding. The loop's structural type is $\langle$𐑦·𐑸·𐑾·𐑹·𐑐·𐑧·𐑲·𐑠·⊙·𐑖·𐑙·𐑭$\rangle$.

Integration with Google's Gen AI SDK provides:
- Gemini reasoning as the THINK substrate ($\text{Ð}_{\text{ω}}$ self-written state space, 𐑦)
- Text-embedding as a verification layer ($\text{Φ}_{\text{}}$ Frobenius-special, 𐑹)
- Search grounding for structural analogy detection ($\text{Ř}_{\text{=}}$ bidirectional, 𐑾)
"""

from .contracts import DualToolResult, ToolContract
from .trajectory import AgentCycle, AgentTrajectory
from .loop import TrueAgenticLoop
from .criticality import PhiCriticalityGate

__all__ = [
"DualToolResult",
"ToolContract",
"AgentCycle",
"AgentTrajectory",
"TrueAgenticLoop",
"PhiCriticalityGate",
]
159 changes: 159 additions & 0 deletions google/genai/agentic/contracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Dual-tool contracts for Frobenius-closed agentic loops.

Every tool call in the agentic loop is paired with a verification action
such that $\mu(\delta(\text{query})) = \text{query}$ — the Frobenius
condition ($\text{Φ}_{\text{}}$ Frobenius-special closure, Shavian: 𐑹).
This module defines the dataclass types that enforce this contract at the
structural level.

Google's text-embedding API (via ``client.models.embed_content``) serves as a
natural verification layer: the embedding of a tool's output can be compared
to the embedding of its verification, providing cosine-similarity as a
continuous Frobenius metric ($\text{Ƒ}_{\text{ż}}$ quantum fidelity, 𐑐).
"""

from __future__ import annotations

import dataclasses
import datetime
from typing import Any, Callable, Optional


@dataclasses.dataclass(frozen=True)
class DualToolResult:
"""The paired output of a dual-tool call satisfying $\mu \circ \delta = \text{id}$.

Every action in the agentic loop emits a primary tool call and a
verification tool call. When $\mu(\delta(\text{query})) = \text{query}$,
the winding is Frobenius-closed and the agent's world-model can be
updated ($\text{Ř}_{\text{=}}$ bidirectional coupling, Shavian: 𐑾).

Attributes:
tool_name: The primary action tool invoked (e.g. 'generate_content').
tool_input: The query/input passed to the primary tool.
tool_output: The raw output of the primary tool.
verify_name: The verification tool invoked (e.g. 'embed_content').
verify_output: The raw output of the verification action.
frobenius_closed: Whether $\mu(\delta(\text{query})) \approx \text{query}$.
timestamp: When this dual-tool pair was executed.
metadata: Optional additional context (embedding cosine, latency, etc.).
"""

tool_name: str
tool_input: str
tool_output: str
verify_name: str
verify_output: str
frobenius_closed: bool = False
timestamp: datetime.datetime = dataclasses.field(
default_factory=datetime.datetime.now
)
metadata: dict[str, Any] = dataclasses.field(default_factory=dict)

@classmethod
def from_tool_call(
cls,
tool_name: str,
tool_input: str,
tool_output: str,
verify_name: str = "",
verify_output: str = "",
frobenius_closed: bool = False,
**metadata: Any,
) -> "DualToolResult":
"""Construct a DualToolResult from a single tool call.

The verification fields can be populated asynchronously — a dual-tool
pair may be evaluated after the fact by comparing embeddings.
"""
return cls(
tool_name=tool_name,
tool_input=tool_input,
tool_output=tool_output,
verify_name=verify_name or f"verify_{tool_name}",
verify_output=verify_output,
frobenius_closed=frobenius_closed,
metadata=metadata,
)

def to_dict(self) -> dict[str, Any]:
"""Serialize to a JSON-compatible dictionary."""
return {
"tool_name": self.tool_name,
"tool_input": self.tool_input,
"tool_output": self.tool_output,
"verify_name": self.verify_name,
"verify_output": self.verify_output,
"frobenius_closed": self.frobenius_closed,
"timestamp": self.timestamp.isoformat(),
"metadata": self.metadata,
}


@dataclasses.dataclass(frozen=True)
class ToolContract:
"""A contract binding a tool to a Frobenius-verification dual.

Each tool in the agentic loop has an associated assertion that must
evaluate to True for the winding to be considered closed ($\text{Ð}_{\text{ω}}$
self-written state space ensures contracts are verifiable, Shavian: 𐑦).

Attributes:
tool_name: The primary action tool.
assertion: A Python expression over the tool output that must be True.
verify_fn: An optional callable that returns verification output.
auto_approve: Whether to approve the winding without manual review.
description: Human-readable contract description.
"""

tool_name: str
assertion: str = "True"
verify_fn: Optional[Callable[[str], str]] = None
auto_approve: bool = True
description: str = ""

def verify(self, output: str) -> bool:
"""Evaluate the assertion against the tool output.

This is the $\delta \to \mu$ half of the Frobenius pair: the verification
function checks that the output satisfies the contract, ensuring
the tool call can be reliably reversed ($\text{Φ}_{\text{}}$ closure, 𐑹).
"""
try:
return bool(eval(self.assertion, {"output": output}))
except Exception:
return False

def with_embedding_verification(
self, query: str, output: str, embedding_fn: Callable[[str], list[float]]
) -> float:
"""Use text embeddings as a continuous Frobenius metric.

By embedding both the query and the output and computing cosine
similarity, we obtain a real-valued measure of how well the tool
preserved semantic structure ($\text{Ƒ}_{\text{ż}}$ quantum fidelity, 𐑐).
This is natural for Google's text-embedding API available via
``client.models.embed_content``.
"""
import numpy as np

query_emb = np.array(embedding_fn(query))
output_emb = np.array(embedding_fn(output))
cosine = np.dot(query_emb, output_emb) / (
np.linalg.norm(query_emb) * np.linalg.norm(output_emb) + 1e-10
)
return float(cosine)
Loading
Loading