# ADK-Go Integration Pattern ## Summary Tool definitions and callback patterns for Google ADK-Go agents consuming Episteme. Covers query, assert, constraint check, and trace operations with proper struct tags and callback signatures. ## Core Mechanism ADK-Go agents interact with Episteme through: 1. **Tools** - Structured operations (query, assert, trace) defined as Go structs 2. **Callbacks** - Hooks for pre-flight checks and audit logging 3. **State** - Session state for agent-to-agent communication ## Tool Definition Pattern All Episteme tools follow this structure: ```go import ( "google.golang.org/adk/tool" "google.golang.org/adk/tool/functiontool" ) type [Operation]Input struct { // Required fields (no omitempty) Subject string `json:"subject" jsonschema:"Entity to query (e.g., auth/jwt)"` Predicate string `json:"predicate" jsonschema:"Relation to query (e.g., signing_algorithm)"` // Optional fields (with omitempty) Lens string `json:"lens,omitempty" jsonschema:"Resolution: consensus, authority, recency, constraints"` } type [Operation]Output struct { Value interface{} `json:"value"` Confidence float32 `json:"confidence"` QueryID string `json:"query_id"` // CRITICAL: for audit trail Error string `json:"error,omitempty"` } func [operation](ctx tool.Context, input [Operation]Input) [Operation]Output { // 1. Call Episteme API // 2. Return structured result with QueryID } // Register with functiontool.New() tool, err := functiontool.New( functiontool.Config{ Name: "episteme_query", Description: "Query Episteme knowledge graph", }, queryEpisteme, ) ``` ## Standard Tools ### Query Tool ```go type QueryInput struct { Subject string `json:"subject" jsonschema:"Entity to query (e.g., auth/jwt)"` Predicate string `json:"predicate" jsonschema:"Relation to query (e.g., signing_algorithm)"` Lens string `json:"lens,omitempty" jsonschema:"Resolution: consensus, authority, recency, constraints"` Lifecycle string `json:"lifecycle,omitempty" jsonschema:"Filter: proposed, approved, deprecated"` MinConfidence float32 `json:"min_confidence,omitempty" jsonschema:"Minimum confidence threshold (0.0-1.0)"` AsOf string `json:"as_of,omitempty" jsonschema:"Time-travel: ISO8601 timestamp"` } type QueryOutput struct { Value interface{} `json:"value"` Confidence float32 `json:"confidence"` Lifecycle string `json:"lifecycle"` Sources []Source `json:"sources"` QueryID string `json:"query_id"` } ``` ### Assert Tool ```go type AssertInput struct { Subject string `json:"subject" jsonschema:"Entity being described"` Predicate string `json:"predicate" jsonschema:"Relation being asserted"` Object interface{} `json:"object" jsonschema:"Value being claimed"` SourceHash string `json:"source_hash" jsonschema:"BLAKE3 hash of evidence"` Confidence float32 `json:"confidence" jsonschema:"Certainty level (0.0-1.0)"` Lifecycle string `json:"lifecycle,omitempty" jsonschema:"proposed, under_review, approved"` ParentHash string `json:"parent_hash,omitempty" jsonschema:"Hash of assertion being updated"` Meta *AssertMeta `json:"meta,omitempty" jsonschema:"Additional metadata"` } type AssertMeta struct { ForbiddenAlternative string `json:"forbidden_alternative,omitempty"` Reason string `json:"reason,omitempty"` } type AssertOutput struct { Hash string `json:"hash"` Success bool `json:"success"` Error string `json:"error,omitempty"` } ``` ### Constraint Check Tool ```go type ConstraintCheckInput struct { Context string `json:"context" jsonschema:"Domain context (e.g., python_http, auth_jwt)"` } type ConstraintCheckOutput struct { Constraints []Constraint `json:"constraints"` } type Constraint struct { Subject string `json:"subject"` MustUse string `json:"must_use,omitempty"` Forbidden string `json:"forbidden,omitempty"` Reason string `json:"reason"` } ``` ### Trace Tool (SRE) ```go type TraceInput struct { AgentID string `json:"agent_id" jsonschema:"Agent to trace"` From string `json:"from" jsonschema:"Start time (ISO8601 or relative like -6h)"` To string `json:"to,omitempty" jsonschema:"End time (default: now)"` Subject string `json:"subject,omitempty" jsonschema:"Filter by subject pattern (e.g., auth/*)"` } type TraceOutput struct { Queries []QueryTrace `json:"queries"` } type QueryTrace struct { QueryID string `json:"query_id"` Timestamp string `json:"timestamp"` Subject string `json:"subject"` Predicate string `json:"predicate"` Lens string `json:"lens"` Result string `json:"result"` Confidence float32 `json:"confidence"` Contributing []string `json:"contributing_assertions"` } ``` ## Callback Integration ### BeforeToolCallback - Constraint Pre-flight Critical for preventing repeat mistakes: ```go agent, err := llmagent.New(llmagent.Config{ Name: "implementation_agent", Model: model, Tools: []tool.Tool{queryTool, assertTool}, BeforeToolCallback: func(ctx agent.CallbackContext, call *tool.Call) (*tool.Call, error) { // Check constraints before any tool that could use wrong patterns if needsConstraintCheck(call) { constraints := checkConstraints(ctx, extractContext(call)) for _, c := range constraints { if violates(call, c) { return nil, fmt.Errorf("blocked: %s is forbidden - %s", c.Forbidden, c.Reason) } } } return call, nil }, }) ``` ### AfterModelCallback - Audit Trail Log agent decisions for debugging: ```go AfterModelCallback: func(ctx agent.CallbackContext, resp *model.LLMResponse) (*model.LLMResponse, error) { // Log what the agent decided for future tracing decision := extractDecision(resp) logToEpisteme(ctx, AuditEntry{ AgentID: ctx.Agent().Name(), Timestamp: time.Now(), Decision: decision, Context: ctx.Session().State(), }) return resp, nil }, ``` ### AfterToolCallback - Error Learning Trigger Gardener when tools fail: ```go AfterToolCallback: func(ctx agent.CallbackContext, call *tool.Call, result *tool.Result) (*tool.Result, error) { if result.Error != nil { // Notify Gardener of the failure for TrustRank back-propagation notifyGardener(ctx, GardenerEvent{ AgentID: ctx.Agent().Name(), ToolCall: call, Error: result.Error, QueryID: extractQueryID(call), }) } return result, nil }, ``` ## Agent-Specific Patterns ### Lead Orchestrator Fast queries with confidence thresholds: ```go result := queryEpisteme(ctx, QueryInput{ Subject: "auth/jwt", Predicate: "signing_algorithm", Lens: "authority", MinConfidence: 0.8, }) if result.Confidence < 0.8 { // Escalate to human or research agent return escalate(ctx, result) } ``` ### Implementation Agent Approved patterns only: ```go result := queryEpisteme(ctx, QueryInput{ Subject: "auth/jwt", Predicate: "signing_algorithm", Lens: "authority", Lifecycle: "approved", // CRITICAL: never use proposed patterns }) ``` ### Research Agent Store with uncertainty and contradictions: ```go assertKnowledge(ctx, AssertInput{ Subject: "jwt_rotation", Predicate: "best_practice", Object: "rotate_daily", SourceHash: hashURL(sourceURL), Confidence: 0.7, // Express uncertainty Lifecycle: "proposed", }) // Store contradicting information - don't flatten assertKnowledge(ctx, AssertInput{ Subject: "jwt_rotation", Predicate: "best_practice", Object: "rotate_weekly", SourceHash: hashURL(differentSourceURL), Confidence: 0.6, Lifecycle: "proposed", }) ``` ### Human Supervisor Time-travel and corrections: ```go // What was believed during the incident? result := queryEpisteme(ctx, QueryInput{ Subject: "auth/jwt", Predicate: "signing_algorithm", AsOf: "2024-01-15T21:00:00Z", }) // Correct the record supersede(ctx, SupersedeInput{ Hash: badAssertionHash, Reason: "Proposal treated as approved - was never reviewed", Type: "Invalidate", }) ``` ### On-Call SRE Trace agent decisions: ```go traces := traceAgentQueries(ctx, TraceInput{ AgentID: "deployment-agent", From: "-6h", Subject: "auth/*", }) for _, t := range traces.Queries { fmt.Printf("[%s] %s/%s via %s -> %s (%.2f)\n", t.Timestamp, t.Subject, t.Predicate, t.Lens, t.Result, t.Confidence) fmt.Printf(" Contributing: %v\n", t.Contributing) } ``` ## State vs Episteme | Use | Mechanism | |-----|-----------| | Agent-to-agent handoff (same session) | Session State + OutputKey | | Persistent organizational knowledge | Episteme Assert | | What was decided in this conversation | Session State | | What should all agents know forever | Episteme Assert | | Temporary working data | `temp:` prefixed state keys | | Audit trail | Episteme QueryAudit | ## Related - [services/assertion.md](../services/assertion.md) - Core assertion structure - [services/lens.md](../services/lens.md) - Lens resolution strategies - [services/lifecycle.md](../services/lifecycle.md) - Lifecycle stage filtering - [features/gardener.md](../features/gardener.md) - Error back-propagation - [features/query-audit.md](../features/query-audit.md) - Trace and debug