Skip to content

Commit 73a644f

Browse files
authored
fix(agent): improve ADK setup logic (flare-foundation#104)
2 parents df12d44 + b90d8e9 commit 73a644f

File tree

15 files changed

+286
-530
lines changed

15 files changed

+286
-530
lines changed

.env.example

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ GCP__TAGS=flare-ai,http-server,https-server
4343

4444
# API key for using Google Gemini (https://aistudio.google.com/app/apikey).
4545
AGENT__GEMINI_API_KEY="your_api_key"
46-
GOOGLE_API_KEY="your_api_key"
4746

4847
# Gemini model to use (e.g. gemini-2.5-flash, gemini-2.5-pro)
4948
# AGENT__GEMINI_MODEL="gemini-2.5-flash"

README.md

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
# Flare AI Kit
22

3-
SDK for building **verifiable AI Agents** on Flare using Confidential Space.
3+
SDK for building **verifiable AI Agents** on Flare using Confidential Space Trusted Execution Environments (TEEs).
44

55
> [!WARNING]
66
>
7-
> Flare AI Kit is currently under active development (pre-release/alpha stage).
7+
> Flare AI Kit is currently under active development (alpha stage).
88
>
99
> Interfaces, APIs, and functionalities may change frequently and potentially in backward-incompatible ways before a stable release.
1010
> Use with caution.
1111
1212
## ✨ Features
1313

14-
- **Verifiable Execution**: Run logic in hardware‑isolated TEEs - [GCP Confidential Space TDX](https://cloud.google.com/confidential-computing/confidential-space/docs/confidential-space-overview).
15-
- **Consensus Engine**: Multi‑agent [Consensus Learning](https://arxiv.org/abs/2402.16157) via [Google Agent2Agent](https://github.com/a2aproject/A2A) protocol.
16-
- **Strictly‑Typed Agents**: Build with [PydanticAI](https://ai.pydantic.dev) to enforce structured outputs across 200+ LLMs.
17-
- **Flare Protocol Integration**: [FTSO](https://dev.flare.network/ftso/overview), [FDC](https://dev.flare.network/fdc/overview), [FAssets](https://dev.flare.network/fassets/overview), plus ecosystem dApps like [Sceptre](http://sceptre.fi) and [SparkDEX](https://sparkdex.ai).
18-
- **Social Intelligence**: Analytics and connectors for X, Telegram, Farcaster.
14+
- **Verifiable execution**: Run logic inside Intel TDX TEEs via [GCP Confidential Space](https://cloud.google.com/confidential-computing/confidential-space/docs/confidential-space-overview).
15+
- **Multi-agent consensus**: Majority/Tournament/[Consensus Learning](https://arxiv.org/abs/2402.16157) via [Google Agent2Agent](https://github.com/a2aproject/A2A) protocol.
16+
- **Agent framework**: Built on [Google ADK](https://google.github.io/adk-docs/) with tool-calling, orchestration and evaluation.
17+
- **Flare integration**: [FTSO](https://dev.flare.network/ftso/overview), [FDC](https://dev.flare.network/fdc/overview), [FAssets](https://dev.flare.network/fassets/overview) + ecosystem dApps ([Sceptre](https://sceptre.fi), [SparkDEX](https://sparkdex.ai), ...).
18+
- **Social connectors**: X, Telegram, Farcaster.
1919

2020
## 🏗️ Architecture
2121

@@ -80,22 +80,17 @@ flowchart TD
8080

8181
- [uv](https://github.com/astral-sh/uv) with Python >= 3.12
8282
- [Docker](https://www.docker.com).
83+
- (For deployment) Authenticated [gcloud CLI](https://cloud.google.com/sdk/docs/install).
8384

84-
1. **Clone the repo:**
85+
1. **Clone & configure:**
8586

8687
```bash
8788
git clone --recursive https://github.com/flare-foundation/flare-ai-kit.git
8889
cd flare-ai-kit
90+
cp .env.example .env # add API keys and settings
8991
```
9092

91-
2. **Configure your environment:**
92-
93-
```bash
94-
# Copy the template and add your models, API keys etc.
95-
cp .env.example .env
96-
```
97-
98-
3. **Install dependencies:**
93+
2. **Install:**
9994

10095
```bash
10196
uv sync --all-extras
@@ -106,22 +101,15 @@ flowchart TD
106101
Run the following commands to format, lint, type-check, and test your code before committing.
107102

108103
```bash
109-
# Format, lint, and auto-fix
110-
uv run ruff format
111-
uv run ruff check --fix
112-
113-
# Run static type checking
114-
uv run pyright
115-
116-
# Run tests
117-
uv run pytest
104+
# Format, lint, type-check, test
105+
uv run ruff format && uv run ruff check --fix && uv run pyright && uv run pytest
118106
```
119107

120-
## 🚧 Build with Docker
108+
## 🐳 Docker
121109

122110
```bash
123111
docker build -t flare-ai-kit .
124-
docker run -rm --env-file .env flare-ai-kit
112+
docker run --rm --env-file .env flare-ai-kit
125113
```
126114

127115
## ☁️ Deploy to Confidential Space
@@ -134,12 +122,14 @@ docker run -rm --env-file .env flare-ai-kit
134122

135123
```bash
136124
chmod +x gcloud-deploy.sh
137-
./gcloud-deploy.sh # For verbose mode: ./gcloud-deploy.sh -v
125+
./gcloud-deploy.sh # verbose: ./gcloud-deploy.sh -v
138126
```
139127

140128
## 🤝 Contributing
141129

142-
Contributions are highly encouraged! Please review the [CONTRIBUTING.md](CONTRIBUTING.md) guide for details on code style (Conventional Commits, Strict Typing), testing, and the PR process.
130+
See [CONTRIBUTING.md](CONTRIBUTING.md).
131+
We use Conventional Commits, Ruff/Pyright gates, and pytest.
132+
Please include tests and update docs for any user-visible changes.
143133

144134
## 📜 License
145135

examples/05_ingest_pdf.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22

33
import asyncio
44
import json
5+
import os
56
import re
67
from pathlib import Path
78
from typing import Any
89
from unittest.mock import AsyncMock, mock_open, patch
910

1011
from data.create_sample_invoice import create_invoice_and_build_template
12+
from google.adk.agents import Agent
1113
from google.adk.runners import Runner
1214
from google.adk.sessions import InMemorySessionService
1315
from google.genai import types
1416

1517
from flare_ai_kit import FlareAIKit
16-
from flare_ai_kit.agent.adk_agent import pdf_agent
18+
from flare_ai_kit.agent.pdf_tools import read_pdf_text_tool
1719
from flare_ai_kit.config import AppSettings
1820
from flare_ai_kit.ingestion.settings import (
1921
IngestionSettings,
@@ -55,18 +57,22 @@ def _json_from(text: str) -> dict[str, Any]:
5557

5658

5759
async def parse_pdf_to_template_json(
58-
pdf: str | Path, template: PDFTemplateSettings, max_pages: int | None = None
60+
agent: Agent,
61+
pdf: str | Path,
62+
template: PDFTemplateSettings,
63+
max_pages: int | None = None,
5964
) -> dict[str, Any]:
6065
"""Setup in-memory ADK agent, give it the PDF, template and prompt."""
6166
pdf = Path(pdf)
6267
svc = InMemorySessionService()
6368
await svc.create_session(app_name="app", user_id="u", session_id="s")
64-
runner = Runner(agent=pdf_agent, app_name="app", session_service=svc)
69+
runner = Runner(agent=agent, app_name="app", session_service=svc)
6570

6671
msg = types.Content(
6772
role="user", parts=[types.Part(text=_prompt(pdf, template, max_pages))]
6873
)
6974
final_text = None
75+
print(f"Calling {agent.name} using model: {agent.model}")
7076
async for ev in runner.run_async(user_id="u", session_id="s", new_message=msg):
7177
if ev.is_final_response() and ev.content and ev.content.parts:
7278
final_text = ev.content.parts[0].text
@@ -97,6 +103,33 @@ async def main() -> None:
97103
),
98104
)
99105

106+
# Inject Gemini API Key
107+
if app_settings.agent and app_settings.agent.gemini_api_key:
108+
api_key = app_settings.agent.gemini_api_key.get_secret_value()
109+
os.environ["GOOGLE_API_KEY"] = api_key
110+
111+
# Create ADK agent with tool access.
112+
pdf_agent_instruction = (
113+
"You are a PDF extraction agent. "
114+
"Independently read PDFs using tools and return ONLY JSON matching this schema:\n"
115+
"{\n"
116+
' "template_name": string,\n'
117+
' "fields": [ {"field_name": string, "value": string|null}, ... ]\n'
118+
"}\n"
119+
"- Always call read_pdf_text with the provided file path.\n"
120+
"- Use ONLY the template JSON (field order and names) provided by the user to decide what to extract.\n"
121+
"- If a field is not found, set its value to null.\n"
122+
"- Do not include prose or explanations. Reply with a single JSON object only."
123+
)
124+
125+
# Construct the Agent instance using the imported tool and settings
126+
pdf_agent = Agent(
127+
name="flare_pdf_agent",
128+
model=app_settings.agent.gemini_model,
129+
tools=[read_pdf_text_tool],
130+
instruction=pdf_agent_instruction,
131+
)
132+
100133
# Mock onchain contract posting
101134
with (
102135
patch(
@@ -114,7 +147,9 @@ async def main() -> None:
114147
print("📄 extracted:", mock_post.call_args[0][0])
115148

116149
# Agent PDF parsing
117-
structured = await parse_pdf_to_template_json(pdf_path, template, max_pages=1)
150+
structured = await parse_pdf_to_template_json(
151+
pdf_agent, pdf_path, template, max_pages=1
152+
)
118153
print("🧩 agent JSON:", json.dumps(structured, indent=2))
119154

120155

0 Bytes
Binary file not shown.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ ignore = ["D203", "D212", "COM812", "S105", "D401", "D104", "ANN401", "ISC003",
105105
"src/flare_ai_kit/agent/adk_agent.py" = ["E501"]
106106
"src/flare_ai_kit/agent/ecosystem_tools_wrapper.py" = ["PLC0415"]
107107
"tests/**/*.py" = ["S", "ARG", "PLR2004", "SLF001", "BLE001", "E501", "T201", "D", "ANN", "F821", "PLC"]
108-
"examples/**/*.py" = ["D", "T201", "BLE001", "INP001"]
108+
"examples/**/*.py" = ["D", "T201", "BLE001", "INP001", "E501"]
109109

110110
[tool.pyright]
111111
pythonVersion = "3.12"

src/flare_ai_kit/agent/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
from .settings import AgentSettings
2+
from .tools import TOOL_REGISTRY
23

3-
__all__ = ["AgentSettings"]
4+
__all__ = ["TOOL_REGISTRY", "AgentSettings"]

src/flare_ai_kit/agent/adk/__init__.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

src/flare_ai_kit/agent/adk_agent.py

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/flare_ai_kit/agent/context.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Module provides a single, shared instance of the Flare AI Kit SDK for agent."""
2+
3+
from flare_ai_kit.main import FlareAIKit
4+
5+
# This single `kit` instance will be imported and used by all agent tools.
6+
# It will be initialized once when the module is first imported.
7+
kit = FlareAIKit(config=None)

0 commit comments

Comments
 (0)