Documentation Index Fetch the complete documentation index at: https://docs.civic.com/llms.txt
Use this file to discover all available pages before exploring further.
Connect a Google Agent Development Kit (ADK) agent to Civic using streamable HTTP transport. Reference implementations are available in Python (Claude), TypeScript (Gemini), and Go (Gemini).
Architecture
User Message
|
v
Runner --> LlmAgent --> LLM (Claude / Gemini)
| |
| v
| MCPToolset --(StreamableHTTP)--> Civic MCP Hub
| | |
v v v
Session Tool Discovery Guardrails / Audit / Revocation
+ Invocation
Component Purpose LlmAgent Wraps an LLM with instructions and tools MCPToolset Connects to Civic’s MCP Hub, discovers and invokes tools Runner Orchestrates agent execution and streams response events SessionService Manages conversation state
Prerequisites
Get Your Credentials How to generate a Civic token and configure toolkit URL parameters
Environment Variables
All implementations require:
CIVIC_URL = https://app.civic.com/hub/mcp? profile = your-toolkit
CIVIC_TOKEN = your-civic-token
Plus an LLM API key depending on the language — see each tab below.
Python (Claude)
TypeScript (Gemini)
Go (Gemini)
Requirements: Python 3.10+, uv (recommended) or pip, an Anthropic API key Installation pip install google-adk python-dotenv
Additional env var ANTHROPIC_API_KEY = your-anthropic-key
Connecting to Civic ADK has native Anthropic model support via google.adk.models.anthropic_llm.Claude — no LiteLlm dependency needed. Register Claude with the model registry and reference the model by string: import os
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
from google.adk.models.anthropic_llm import Claude
from google.adk.models.registry import LLMRegistry
load_dotenv()
# Register Claude for native Anthropic model support
LLMRegistry.register(Claude)
root_agent = Agent(
model = "claude-sonnet-4-6" ,
name = "civic_assistant" ,
instruction = "You are a helpful assistant with access to external tools through Civic." ,
tools = [
McpToolset(
connection_params = StreamableHTTPConnectionParams(
url = os.environ[ "CIVIC_URL" ],
headers = { "Authorization" : f "Bearer { os.environ[ 'CIVIC_TOKEN' ] } " },
),
)
],
)
Running the Agent Option A: ADK web console ADK ships with a built-in development UI: Open http://localhost:8000 and select civic_agent from the dropdown. Option B: Programmatic runner import asyncio
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
async def main ():
session_service = InMemorySessionService()
runner = Runner(
agent = root_agent,
app_name = "my-app" ,
session_service = session_service,
)
await session_service.create_session(
app_name = "my-app" , user_id = "user-1" , session_id = "session-1"
)
message = types.Content(
role = "user" ,
parts = [types.Part( text = "What events do I have today?" )],
)
async for event in runner.run_async(
user_id = "user-1" , session_id = "session-1" , new_message = message
):
if event.is_final_response():
for part in event.content.parts:
if part.text:
print (part.text)
asyncio.run(main())
Use types.Part(text=...) — not types.Part.from_text(...). The from_text class method was removed in recent versions of the Google Gen AI SDK.
Requirements: Node.js v18+, a Google Gemini API key Installation npm install @google/adk dotenv
Additional env var GOOGLE_GENAI_API_KEY = your-google-genai-api-key
Connecting to Civic The TypeScript ADK uses MCPToolset with StreamableHTTPConnectionParams. Gemini is configured automatically via the GOOGLE_GENAI_API_KEY env var: import 'dotenv/config' ;
import {
LlmAgent ,
Runner ,
InMemorySessionService ,
MCPToolset ,
isFinalResponse ,
stringifyContent ,
} from '@google/adk' ;
import type { Content } from '@google/genai' ;
const civicUrl = process . env . CIVIC_URL ! ;
const civicToken = process . env . CIVIC_TOKEN ! ;
const mcpToolset = new MCPToolset ({
type: 'StreamableHTTPConnectionParams' ,
url: civicUrl ,
transportOptions: {
requestInit: {
headers: { Authorization: `Bearer ${ civicToken } ` },
},
},
});
const agent = new LlmAgent ({
model: 'gemini-2.5-flash' ,
name: 'civic_assistant' ,
instruction: 'You are a helpful assistant. Use the available tools when they can help.' ,
tools: [ mcpToolset ],
});
Running the Agent async function main () {
const sessionService = new InMemorySessionService ();
const runner = new Runner ({
appName: 'civic-adk-ts' ,
agent ,
sessionService ,
});
const session = await sessionService . createSession ({
appName: 'civic-adk-ts' ,
userId: 'user-1' ,
});
const message : Content = {
role: 'user' ,
parts: [{ text: 'What tools do you have?' }],
};
for await ( const event of runner . runAsync ({
userId: 'user-1' ,
sessionId: session . id ,
newMessage: message ,
})) {
if ( isFinalResponse ( event )) {
const text = stringifyContent ( event );
if ( text ) console . log ( text );
}
}
}
main ();
Requirements: Go 1.23+, a Google API key Additional env var GOOGLE_API_KEY = your-google-api-key
Connecting to Civic The Go ADK uses a custom http.RoundTripper to inject the Civic Bearer token into every outbound MCP request: package main
import (
" context "
" net/http "
" os "
mcp " github.com/modelcontextprotocol/go-sdk/mcp "
" google.golang.org/adk/agent/llmagent "
" google.golang.org/adk/model/gemini "
" google.golang.org/adk/runner "
" google.golang.org/adk/session "
" google.golang.org/adk/tool "
" google.golang.org/adk/tool/mcptoolset "
" google.golang.org/genai "
)
// bearerTransport injects Authorization into every request.
type bearerTransport struct {
token string
base http . RoundTripper
}
func ( t * bearerTransport ) RoundTrip ( req * http . Request ) ( * http . Response , error ) {
req = req . Clone ( req . Context ())
req . Header . Set ( "Authorization" , "Bearer " + t . token )
return t . base . RoundTrip ( req )
}
Running the Agent func main () {
ctx := context . Background ()
civicURL := os . Getenv ( "CIVIC_URL" )
civicToken := os . Getenv ( "CIVIC_TOKEN" )
llm , _ := gemini . NewModel ( ctx , "gemini-2.5-flash" , & genai . ClientConfig {
APIKey : os . Getenv ( "GOOGLE_API_KEY" ),
})
httpClient := & http . Client {
Transport : & bearerTransport { token : civicToken , base : http . DefaultTransport },
}
transport := & mcp . StreamableClientTransport {
Endpoint : civicURL ,
HTTPClient : httpClient ,
DisableStandaloneSSE : true ,
}
mcpTools , _ := mcptoolset . New ( mcptoolset . Config { Transport : transport })
root , _ := llmagent . New ( llmagent . Config {
Name : "civic_assistant" ,
Instruction : "You are a helpful assistant. Use the available tools when they can help." ,
Model : llm ,
Toolsets : [] tool . Toolset { mcpTools },
})
sessionSvc := session . InMemoryService ()
r , _ := runner . New ( runner . Config {
AppName : "civic-adk-go" ,
Agent : root ,
SessionService : sessionSvc ,
})
sess , _ := sessionSvc . Create ( ctx , & session . CreateRequest {
AppName : "civic-adk-go" ,
UserID : "user-1" ,
})
userContent := & genai . Content {
Role : "user" ,
Parts : [] * genai . Part {{ Text : "What tools do you have?" }},
}
for event , err := range r . Run ( ctx , "user-1" , sess . Session . ID (), userContent , nil ) {
if err != nil || event == nil || event . Content == nil {
continue
}
for _ , part := range event . Content . Parts {
if part . Text != "" {
fmt . Print ( part . Text )
}
}
}
}
Production Configuration
Lock to a specific toolkit using the profile URL parameter:
CIVIC_URL = https://app.civic.com/hub/mcp? profile = your-production-toolkit
Reference Implementation
google-adk-reference-implementation-civic Complete implementations in Python, TypeScript, and Go with deployment guides
Next Steps
Agent Deployment Production deployment guide: profile locking, URL params, authentication
Guardrails Constrain what tools your agent can call
Audit Trail Query what your agent did via Civic Chat
Get Credentials Token generation and URL parameter reference