Skip to content

feat: support agentic ai + gaurd rails #72

Open
amitgilad3 wants to merge 4 commits into
mainfrom
gaurd_rails
Open

feat: support agentic ai + gaurd rails #72
amitgilad3 wants to merge 4 commits into
mainfrom
gaurd_rails

Conversation

@amitgilad3
Copy link
Copy Markdown
Contributor

@amitgilad3 amitgilad3 commented May 6, 2026

Summary by CodeRabbit

  • New Features

    • Added guardrails system with built-in guards, HTTP webhooks, and custom Python scripts
    • Introduced agentic context tracking to associate queries with agents and conversations
    • New admin UI for browsing agents, viewing conversations, and managing guardrails
    • Enhanced query history with agent identity, conversation tracking, and guard action visibility
  • Documentation

    • Added comprehensive guardrails architecture documentation
    • Added agentic context integration guide

@amitgilad3 amitgilad3 requested a review from Copilot May 6, 2026 14:21
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Caution

Review failed

Failed to post review comments

📝 Walkthrough

Walkthrough

This PR introduces guardrails—a rule-based safety framework for query execution—and agentic context tracking. It adds a new guardrails crate with built-in guards and chain execution, extends sessions and queries to carry agent/conversation metadata, integrates guard checks into the dispatch pipeline, and provides admin APIs and frontend UI for managing guardrails and browsing agent/conversation history. Database migrations support the new query metadata and guardrails configuration storage.

Changes

Guardrails and Agentic Context System

Layer / File(s) Summary
Core Types & Configuration
crates/queryflux-core/src/config.rs, crates/queryflux-core/src/session.rs
ProxyConfig adds optional guardrails field. SessionContext introduces agent_context field carrying agent ID, conversation ID, step index, tool call ID, and query intent; new QueryIntent enum classifies query type from headers or SQL heuristics; resolution method parses headers or SQL-style keys.
Guardrails Framework
crates/queryflux-guardrails/src/lib.rs, crates/queryflux-guardrails/src/built_in.rs, crates/queryflux-guardrails/src/chain.rs, crates/queryflux-guardrails/src/context.rs, crates/queryflux-guardrails/src/config.rs, Cargo.toml
New crate introduces GuardResult (Allow/Warn/Deny), GuardContext, GuardLayer (Input/Plan/Output), and Guard trait. Implements built-in guards (ReadOnlyGuard, RowLimitGuard, RequirePredicateGuard) with SQL parsing and fallback heuristics. GuardChain executes guards sequentially, collecting actions and signaling denials. GuardChainConfig models global and per-group overrides with support for BuiltIn, PythonScript, and HttpWebhook guard kinds.
Frontend Session & Context Plumbing
crates/queryflux-frontend/src/flight_sql/mod.rs, crates/queryflux-frontend/src/mysql_wire/mod.rs, crates/queryflux-frontend/src/postgres_wire/mod.rs, crates/queryflux-frontend/src/snowflake/http/handlers/session.rs, crates/queryflux-frontend/src/snowflake/http/handlers/query.rs, crates/queryflux-frontend/src/snowflake/sql_api/handlers.rs, crates/queryflux-frontend/src/trino_http/handlers.rs
All wire protocol handlers initialize SessionContext with agent_context field (set to None or resolved from headers/startup params). HTTP handlers (Snowflake, Trino) collect incoming request headers into extra context map.
Dispatch Guard Execution & Propagation
crates/queryflux-frontend/src/dispatch.rs, crates/queryflux-frontend/src/state.rs
dispatch_query builds GuardContext from QueryContext, runs guard chain pre-submission, and denies on first deny with proper error handling. QueryContext and QueryOutcome extended with agent_context, guard_actions, and was_guard_blocked. SyncQuerySetup carries guard_actions for final outcome merge. QueryRecord enriched with agent/conversation metadata and guard actions for metrics/fingerprinting. LiveConfig holds optional Arc<GuardChain>.
Admin Endpoints & Handlers
crates/queryflux-frontend/src/admin.rs
New protected routes /admin/agents, /admin/conversations, /admin/conversations/{id}, and /admin/config/guardrails (GET/PUT). Handlers list agents with counts and activity windows, list/filter conversations by agent, fetch conversation steps, and read/write guardrails config via admin store.
Persistence Layer
crates/queryflux-persistence/src/metrics_store.rs, crates/queryflux-persistence/src/query_history.rs, crates/queryflux-persistence/src/script_library.rs, crates/queryflux-persistence/src/postgres/mod.rs, crates/queryflux-persistence/src/postgres/migrations/20260505000001_agent_context.sql, crates/queryflux-persistence/src/postgres/migrations/20260505000002_guard_script_kind.sql, crates/queryflux-persistence/src/postgres/migrations/20260506000001_guardrails.sql, crates/queryflux-persistence/src/in_memory.rs
GuardAction struct captures guard evaluation results. QueryRecord and QuerySummary extended with agent_id, conversation_id, step_index, tool_call_id, query_intent, guard_actions, was_guard_blocked. New AgentSummary and ConversationSummary types support agent/conversation analytics. QueryHistoryStore trait updated: removed list_engines, added list_agents, list_conversations, get_conversation. Database migrations add agent context columns, partial indexes, guardrails table, and guard script kind expansion. Postgres adapter enriched to fetch/persist new fields.
Frontend State & Main Integration
crates/queryflux/src/main.rs, crates/queryflux-frontend/Cargo.toml, crates/queryflux/Cargo.toml
Main startup logic builds GuardChain from YAML or DB (DB preferred), manages in-memory AdminStore fallback, integrates guard chain into LiveConfig lifecycle, and supports hot-reload of guardrails. Admin store selection updated for reload scenarios. workspace dependencies and workspace version bumped (0.1.2 → 0.1.3).
Frontend UI Pages & Components
queryflux-studio/app/agents/page.tsx, queryflux-studio/app/agents/[id]/page.tsx, queryflux-studio/app/agents/[id]/conversation-list.tsx, queryflux-studio/app/agents/agent-table.tsx, queryflux-studio/app/agents/agent-detail.tsx, queryflux-studio/app/conversations/page.tsx, queryflux-studio/app/conversations/[id]/page.tsx, queryflux-studio/app/conversations/[id]/conversation-step-detail.tsx, queryflux-studio/app/conversations/conversation-table.tsx, queryflux-studio/app/guardrails/page.tsx, queryflux-studio/app/guardrails/guardrails-editor.tsx, queryflux-studio/app/queries/page.tsx, queryflux-studio/app/queries/query-detail.tsx, queryflux-studio/app/queries/query-table.tsx, queryflux-studio/app/scripts/page.tsx, queryflux-studio/app/client-shell.tsx
New pages for agents (listing with pagination, detail with metrics), conversations (listing, detail with step timeline), and guardrails (config/script editor). Agent/conversation tables with search, sort, filtering. Guard actions rendering in query details and conversation steps. Scripts page refactored for multi-kind support (translation_fixup, guard). Client shell navigation updated with Agents and Guardrails menu items. Query pages enhanced with guard and agent badges.
Studio Component Library & API
queryflux-studio/components/guard-actions-list.tsx, queryflux-studio/components/guard-list.tsx, queryflux-studio/components/group-form-dialog.tsx, queryflux-studio/components/user-script-editor-dialog.tsx, queryflux-studio/lib/api-types.ts, queryflux-studio/lib/api.ts, queryflux-studio/lib/script-templates.ts
New types (GuardAction, AgentSummary, ConversationSummary, GuardSpecDto, GuardrailsConfig) in api-types. New API helpers (getAgents, getConversations, getConversationDetail, getGuardrailsConfig, putGuardrailsConfig). Guard action display components (GuardBadge, GuardActionsList, GuardSummaryBadge). GuardList for managing per-group guards with add/edit/remove/reorder. Group form dialog integration with per-group guardrails. User script editor extended to support guard kind with template and hints. Guard script template added.
Documentation
website/docs/agentic/agent-context.md, website/docs/architecture/guardrails.md, website/sidebars.ts
New docs on agentic context (HTTP headers, SQL params, session replay, guardrail integration) and guardrails architecture (chain concept, built-in/script/webhook guards, per-group overrides, observability). Sidebar updated with Agentic AI category and guardrails architecture link.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Frontend
    participant Dispatch
    participant GuardChain
    participant Engine
    participant Metrics

    Client->>Frontend: Query + Agent Headers<br/>(agent-id, conversation-id, etc.)
    Frontend->>Frontend: Parse headers → SessionContext<br/>(resolve agent_context)
    Frontend->>Dispatch: dispatch_query(SessionContext, SQL)
    Dispatch->>Dispatch: Build QueryContext<br/>(copy agent_context)
    Dispatch->>GuardChain: run(GuardContext, InputLayer)<br/>(raw SQL, engine, agent info)
    GuardChain->>GuardChain: Execute guards sequentially<br/>(ReadOnly, RowLimit, RequirePredicate)
    alt Guard Denies
        GuardChain->>Dispatch: (deny_actions, blocked=true)
        Dispatch->>Metrics: Record Failed<br/>(guard_actions, was_guard_blocked)
        Dispatch->>Client: Error (guard denied)
    else Guards Allow/Warn
        GuardChain->>Dispatch: (allow/warn_actions, blocked=false)
        Dispatch->>Engine: Submit Query<br/>(with guard_actions in context)
        Engine->>GuardChain: run(GuardContext, PlanLayer)
        GuardChain->>Engine: (actions, blocked)
        Engine->>GuardChain: run(GuardContext, OutputLayer)
        GuardChain->>Engine: (actions, blocked)
        Engine->>Dispatch: QueryOutcome<br/>(rows, errors)
        Dispatch->>Metrics: Record QueryRecord<br/>(agent_id, conversation_id,<br/>query_intent, guard_actions,<br/>was_guard_blocked)
        Dispatch->>Client: Result
    end
    Metrics->>Metrics: Index by agent, conversation
Loading
sequenceDiagram
    participant Admin as Studio Admin
    participant API as /admin/agents
    participant Store as Postgres Store
    participant UI as Agent Page

    Admin->>API: GET /admin/agents?limit=50&offset=0
    API->>Store: list_agents(50, 0)
    Store->>Store: Aggregate query_count,<br/>conversation_count per agent<br/>(via query_records)
    Store-->>API: Vec\<AgentSummary\>
    API-->>Admin: JSON response
    Admin->>UI: Display agent table<br/>(agent_id, query count,<br/>conversation count)
    Admin->>UI: Click agent row
    UI->>API: GET /admin/conversations?agent_id=X
    API->>Store: list_conversations(agent_id=X)
    Store-->>API: Vec\<ConversationSummary\>
    API-->>UI: JSON response
    UI->>UI: Render conversation list<br/>(with step counts, blocked flag)
    Admin->>UI: Expand conversation
    UI->>API: GET /admin/conversations/{id}
    API->>Store: get_conversation(id)
    Store-->>API: Vec\<QuerySummary\><br/>(includes guard_actions, agent context)
    API-->>UI: JSON response
    UI->>UI: Timeline view<br/>(guard badges, status, intent)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • lakeops-org/queryflux#56: Overlapping changes to session handling and frontend plumbing (crates/queryflux-core/src/session.rs and multiple frontend modules).
  • lakeops-org/queryflux#20: Both PRs extend ProxyConfig in crates/queryflux-core/src/config.rs with new top-level fields (guardrails vs. admin_api).

Poem

A rabbit hops through guards so tall,
Guarding queries against them all,
With agents tracking every quest,
And conversations put to the test,
The safety net is woven tight,
Where agentic context shines so bright! 🐰✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gaurd_rails

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end “agentic” support to QueryFlux by persisting agent conversation metadata with query history and introducing a guardrails system (configurable via Studio and stored in persistence) to apply SQL safety checks before execution.

Changes:

  • Persist agent context fields (agent_id, conversation_id, step_index, tool_call_id, query_intent) and guardrail audit fields (guard_actions, was_guard_blocked) to query history, plus new Admin API endpoints to browse agents and conversations.
  • Introduce a new queryflux-guardrails crate with built-in guards and wiring into dispatch paths, along with a Studio Guardrails UI/editor.
  • Add documentation + sidebar updates for agent context and guardrails.

Reviewed changes

Copilot reviewed 60 out of 61 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
website/sidebars.ts Adds sidebar entries for Agentic AI docs and Guardrails docs.
website/docs/architecture/guardrails.md New Guardrails documentation page.
website/docs/agentic/agent-context.md New Agentic context documentation page.
queryflux-studio/lib/script-templates.ts Adds starter template for guard scripts.
queryflux-studio/lib/api.ts Adds Studio client functions for agents, conversations, and guardrails config endpoints.
queryflux-studio/lib/api-types.ts Adds types for guardrails config and agent/conversation summaries; extends query history record fields.
queryflux-studio/components/user-script-editor-dialog.tsx Generalizes script editor to support script “kinds” via metadata.
queryflux-studio/components/guard-list.tsx New UI component for editing an ordered list of guards (built-in/webhook/script).
queryflux-studio/components/guard-actions-list.tsx New UI component for rendering guard action audit trails and summary badges.
queryflux-studio/components/group-form-dialog.tsx Adds per-group guard editing (writes to guardrails config).
queryflux-studio/app/scripts/page.tsx Refactors scripts page copy/metadata handling.
queryflux-studio/app/queries/query-table.tsx Adds Guard column and agent pill in query history table.
queryflux-studio/app/queries/query-detail.tsx Adds agent identity and guard action sections; extracts reusable detail content.
queryflux-studio/app/queries/page.tsx UI polish for query history header/pagination.
queryflux-studio/app/guardrails/page.tsx New Guardrails page route.
queryflux-studio/app/guardrails/guardrails-editor.tsx New guardrails editor + guard script library editor.
queryflux-studio/app/conversations/page.tsx New conversations listing page.
queryflux-studio/app/conversations/conversation-table.tsx New sortable/searchable conversations table.
queryflux-studio/app/conversations/[id]/page.tsx New conversation detail timeline page.
queryflux-studio/app/conversations/[id]/conversation-step-detail.tsx Expandable per-step details for conversations.
queryflux-studio/app/client-shell.tsx Adds navigation links for Agents and Guardrails.
queryflux-studio/app/agents/page.tsx New agents activity page.
queryflux-studio/app/agents/agent-table.tsx New sortable/searchable agents table.
queryflux-studio/app/agents/agent-detail.tsx New agent detail side panel (conversations preview).
queryflux-studio/app/agents/[id]/page.tsx New per-agent deep inspection page with stats.
queryflux-studio/app/agents/[id]/conversation-list.tsx New expandable conversation cards/timeline list for an agent.
crates/queryflux/src/main.rs Wires guardrails into LiveConfig; loads config from DB/YAML; adds reload handling.
crates/queryflux/Cargo.toml Adds queryflux-guardrails dependency.
crates/queryflux-persistence/src/script_library.rs Adds guard as a script kind.
crates/queryflux-persistence/src/query_history.rs Extends query history DTOs; adds agent/conversation summary DTOs.
crates/queryflux-persistence/src/postgres/mod.rs Adds agent/conversation queries; stores new query_record fields; persists guardrails config via ProxySettingsStore.
crates/queryflux-persistence/src/postgres/migrations/20260506000001_guardrails.sql Adds guardrails table for stored guard config.
crates/queryflux-persistence/src/postgres/migrations/20260505000002_guard_script_kind.sql Updates user_scripts kind constraint to include guard.
crates/queryflux-persistence/src/postgres/migrations/20260505000001_agent_context.sql Adds agent context + guard audit columns and indexes to query_records.
crates/queryflux-persistence/src/metrics_store.rs Adds GuardAction struct and stores guard audit fields on QueryRecord.
crates/queryflux-persistence/src/lib.rs Exposes new types and extends QueryHistoryStore trait for agents/conversations.
crates/queryflux-persistence/src/in_memory.rs Maps new query history fields in memory; stubs agent/conversation listing methods.
crates/queryflux-metrics/src/lib.rs Re-exports GuardAction for callers.
crates/queryflux-guardrails/src/lib.rs New guardrails crate entrypoint and GuardResult→GuardAction conversion.
crates/queryflux-guardrails/src/context.rs New guardrails context and GuardResult definitions.
crates/queryflux-guardrails/src/config.rs New guardrails config model (layered/global+groups).
crates/queryflux-guardrails/src/chain.rs GuardChain execution logic and tests.
crates/queryflux-guardrails/src/built_in.rs Built-in guards implementation + tests (read_only/row_limit/require_predicate).
crates/queryflux-guardrails/Cargo.toml New crate manifest for guardrails.
crates/queryflux-frontend/src/trino_http/handlers.rs Adds agent_context/guard fields to QueryContext/QueryOutcome for Trino polling path.
crates/queryflux-frontend/src/state.rs Extends LiveConfig/QueryContext/QueryOutcome; records agent + guard fields into QueryRecord.
crates/queryflux-frontend/src/snowflake/tests.rs Updates test LiveConfig initialization for new guard_chain field.
crates/queryflux-frontend/src/snowflake/sql_api/handlers.rs Preserves request headers into SessionContext.extra; initializes agent_context.
crates/queryflux-frontend/src/snowflake/http/handlers/session.rs Initializes agent_context in SessionContext.
crates/queryflux-frontend/src/snowflake/http/handlers/query.rs Preserves request headers into SessionContext.extra; initializes agent_context.
crates/queryflux-frontend/src/postgres_wire/mod.rs Passes startup params into SessionContext.extra and adds agent-context tests.
crates/queryflux-frontend/src/mysql_wire/mod.rs Initializes agent_context; adds tests for SET-based agent context.
crates/queryflux-frontend/src/flight_sql/mod.rs Initializes agent_context in SessionContext.
crates/queryflux-frontend/src/dispatch.rs Runs guardrails before execution on async and sync dispatch paths; threads agent_context.
crates/queryflux-frontend/src/admin.rs Adds agents/conversations endpoints and guardrails config endpoints.
crates/queryflux-frontend/Cargo.toml Adds queryflux-guardrails dependency.
crates/queryflux-e2e-tests/src/harness.rs Updates test LiveConfig initialization for new guard_chain field.
crates/queryflux-core/src/session.rs Adds AgentContext + QueryIntent parsing/inference and session resolver.
crates/queryflux-core/src/config.rs Adds YAML guardrails config structures to ProxyConfig.
CHANGELOG.md Adds 0.1.3 release notes mentioning agentic context + guardrails.
Cargo.toml Adds queryflux-guardrails workspace member and bumps version to 0.1.3.
Cargo.lock Updates workspace crate versions and adds guardrails crate dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1698 to +1713
let cfg = config.guardrails.as_ref()?;
let mut guards: Vec<Box<dyn Guard>> = Vec::new();

for spec in &cfg.global {
match &spec.kind {
GuardKindConfig::BuiltIn => {
let name = spec.name.as_deref().unwrap_or("");
match name {
"read_only" => guards.push(Box::new(ReadOnlyGuard)),
"row_limit" => guards.push(Box::new(RowLimitGuard {
max_rows: spec.max_rows,
})),
"require_predicate" => guards.push(Box::new(RequirePredicateGuard {
applies_to: spec.applies_to.clone().unwrap_or_default(),
})),
other => tracing::warn!(name = other, "Unknown built-in guard name; skipping"),
Comment on lines +1729 to +1734
/// Build a `GuardChain` from the flat JSON format stored by the Studio UI.
///
/// The DB format mirrors `GuardrailsConfig` from the TypeScript API types:
/// `{ global: GuardSpecDto[], groups: Record<string, GuardSpecDto[]> }`.
/// Only the `global` array is used here; per-group dispatch is not yet implemented.
fn build_guard_chain_from_db_value(v: &serde_json::Value) -> Option<Arc<GuardChain>> {
Comment on lines +231 to +253
// Guard chain: runs after translation (SQL is final), before engine submission.
if let Some(chain) = &guard_chain {
let resolved_agent_ctx = session.resolved_agent_context();
let guard_ctx = GuardContext {
sql: &original_sql,
translated_sql: &sql,
engine_type: &adapter.engine_type(),
cluster_group: &group,
user: session.user(),
agent_context: resolved_agent_ctx.as_ref(),
query_tags: &effective_tags,
};
let (guard_actions, was_blocked) = chain.run(&guard_ctx, GuardLayer::Plan).await;
if was_blocked {
state.metrics.on_query_finished(&group.0, &cluster_name.0);
let _ = cluster_manager.release_cluster(&group, &cluster_name).await;
let deny_reason = guard_actions
.iter()
.find(|a| a.action == "deny")
.and_then(|a| a.reason.clone())
.unwrap_or_else(|| "query blocked by guardrail".to_string());
return Err(QueryFluxError::Engine(deny_reason));
}
},
query_tags: effective_tags,
query_params: vec![],
agent_context: session.agent_context.clone(),
Comment on lines +856 to +857
guard_actions: vec![],
was_guard_blocked: false,
Comment on lines +40 to +46
```yaml
guardrails:
global:
plan:
- kind: built_in
name: read_only
```
Comment on lines +131 to +139
```yaml
guardrails:
global:
plan:
- kind:
python_script:
script_id: 42
timeout_ms: 2000
```
Comment on lines +12 to +20
/// Convert a `GuardResult` into a `GuardAction` for audit recording.
pub fn result_to_action(guard_name: &str, result: &GuardResult) -> GuardAction {
match result {
GuardResult::Allow { metadata: _ } => GuardAction {
guard: guard_name.to_string(),
action: "allow".to_string(),
reason: None,
code: None,
},
/// task can atomically swap the whole bundle on each reload tick.
pub struct LiveConfig {
pub router_chain: RouterChain,
/// Guard chain: global guards first, per-group guards appended at dispatch time.
Comment on lines +32 to +36
Return shapes:
{"action": "allow"}
{"action": "allow", "metadata": {"matched_rule": "...", "estimated_rows": "~50k"}}
{"action": "warn", "reason": "scans large table without partition filter"}
{"action": "deny", "reason": "missing WHERE on fct_events", "code": "MISSING_PREDICATE"}
@amitgilad3
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@amitgilad3
Copy link
Copy Markdown
Contributor Author

reference discussion - #51

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants