Corridor Sync
Overview¶
The GenGuardX Corridor Sync system enables you to programmatically manage and version-control your AI assets (Prompts, Models, RAGs, Pipelines, Global Functions, and Reports) directly from your development environment. Using Python decorators and a simple sync command, you can declare and synchronize your components to the GenGuardX platform.
What Can Be Synced?¶
GenGuardX Corridor Sync supports six core component types:
| Component | Purpose | Example Use Case |
|---|---|---|
| Prompt | System instructions, templates, and persona definitions | Customer service chatbot instructions |
| Model | LLM configurations and API integrations | Gemini, GPT, Claude model wrappers |
| RAG | Retrieval-Augmented Generation systems | Database query systems, knowledge base retrieval |
| Pipeline | End-to-end workflows combining multiple components | Complete chatbot with intent classification and response generation |
| Global Function | Reusable utility functions | Data preprocessing, validation, formatting functions |
| Report | Evaluation and monitoring reports with visualizations | Model performance dashboards, bias analysis reports |
Getting Started¶
Step 1: Installation¶
Step 2: Initialize Connection¶
Before syncing any components, you need to authenticate with your GenGuardX instance.
Obtaining Your API Key¶
- Log into your GenGuardX platform
- Navigate to Profile Section → Account Security
- Locate your API Key (format:
eyJI-XXXX-XXXX-XXXX-XXXX-XXXX-3fe3) - Click "How to use this key" to view the initialization code
Initialize in Your Code¶
import genguardx as ggx
# Initialize connection to your GenGuardX instance
ggx.init(
api_url="https://devaisandbox.corridorplatforms.com", # Change for your instance
api_key="your-api-key-here",
)
Important: Replace the api_url if you're using a different GenGuardX instance (e.g., production, staging). The URL should point to your specific deployment.
Component Declaration & Sync¶
Each component type uses a specific decorator pattern. Components can be declared and synced independently or used together in pipelines.
1. Prompts¶
Prompts define system instructions, templates, or conversation guidelines.
Decorator Syntax¶
import genguardx as ggx
@ggx.Prompt.declare(
name='My Prompt Name', # Optional: defaults to function name
group='My Group', # Optional: organizational grouping
task_type='Question Answering', # Optional: Classification | Summarization | etc.
prompt_type='System Instruction', # Optional: User Prompt | Others
prompt_elements=['Persona + Goal', 'Tone', 'Constraints'], # Optional: list of components
)
def my_prompt_function(*, cache: dict = {}, prompt: str = "Your prompt text here"):
"""Docstring describing the prompt purpose."""
# -- BEGIN DEFINITION --
return prompt
# Sync to platform
ggx.sync(my_prompt_function)
2. Models¶
Models wrap LLM API calls with consistent interfaces and cost tracking.
Decorator Syntax¶
import genguardx as ggx
@ggx.Model.declare(
name='My Model Name', # Optional: defaults to function name
group='My Group', # Optional: organizational grouping
ownership_type='Proprietary', # Optional: Proprietary | Open Source
model_type='LLM', # Optional: LLM | Text Embedding | Guardrail | Judge Model | Others
provider='openai', # Optional: openai | google | anthropic | etc. (for API-based models)
model='gpt-4', # Optional: specific model identifier (required if provider is set)
)
def my_model_function(text: str, temperature: float = 0.7, *, cache: dict = {}):
"""Docstring describing the model configuration."""
# -- BEGIN DEFINITION --
# Your model implementation
return {"response": "...", "cost": "..."}
# Sync to platform
ggx.sync(my_model_function)
3. RAGs (Retrieval-Augmented Generation)¶
RAGs connect to knowledge bases, databases, or document stores to retrieve relevant context.
Decorator Syntax¶
import pathlib
import genguardx as ggx
@ggx.Rag.declare(
name='My RAG System', # Optional: defaults to function name
group='My Group', # Optional: organizational grouping
knowledge_base_format='Relational Database', # Optional: Vector Database | Graph Database | etc.
provider=None, # Optional: provider identifier for API-based RAG systems
)
def my_rag_function(
query: str,
*,
cache: dict = {},
knowledge: pathlib.Path = pathlib.Path('data.db')
):
"""Docstring describing the RAG system."""
# -- BEGIN DEFINITION --
# Your RAG implementation
return {"retrieved_data": "...", "query_used": "..."}
# Sync to platform
ggx.sync(my_rag_function)
4. Pipelines¶
Pipelines orchestrate multiple components into complete workflows.
Decorator Syntax¶
import typing as t
import genguardx as ggx
@ggx.Pipeline.declare(
name='My Pipeline', # Optional: defaults to function name
group='My Group', # Optional: organizational grouping
usecase_type='Question Answering', # Optional: Summarization | Translation
task_type='Generative Responses', # Optional: Classification | Templated Responses | etc.
impact='External Facing', # Optional: Internal Only | Internal - with external implications
data_usage=['Customer Specific Data'], # Optional: list of data types
pipeline_type='Chat based - OpenAI Spec', # Required: or 'Custom Return Type'
)
def my_pipeline_function(
user_message: str,
history: list[t.TypedDict("T", {'role': str, 'content': str}, total=False)] = (),
context: t.Optional[dict[str, str]] = None,
*,
cache: dict = {},
):
"""Docstring describing the pipeline workflow."""
# -- BEGIN DEFINITION --
# Your pipeline implementation
return {"output": "...", "context": "..."}
# Sync to platform
ggx.sync(my_pipeline_function)
5. Global Functions¶
Global Functions are reusable utility functions that can be referenced by other components.
Decorator Syntax¶
import genguardx as ggx
@ggx.GlobalFunction.declare(
name='My Utility Function', # Optional: defaults to function name
group='My Group', # Optional: organizational grouping
)
def my_utility_function(input_text: str, max_length: int = 100, *, cache: dict = {}) -> str:
"""Docstring describing the utility function."""
# -- BEGIN DEFINITION --
# Your utility function implementation
return input_text[:max_length]
# Sync to platform
ggx.sync(my_utility_function)
Key Points:
- Global Functions can be called by other components (Pipelines, RAGs, Models, etc.)
6. Reports¶
Reports generate evaluation dashboards with metrics and visualizations for monitoring AI systems.
Decorator Syntax¶
import typing as t
import genguardx as ggx
@ggx.Report.declare(
name='My Evaluation Report', # Optional: defaults to function name
object_types=['PIPELINE', 'FOUNDATION_MODEL'], # Required: list of object types this report evaluates
group='My Group', # Optional: organizational grouping
risk_type='Accuracy', # Optional: Accuracy | Stability | Bias | Vulnerability | Toxicity | Others
task_type='Classification', # Optional: Classification | Templated Responses | etc.
risk_domain='Model Risk Management', # Optional: Model Risk Management | Fair Lending | Technology | Infosec | Others
evaluation_methodology='Statistical / ML Algorithms', # Optional: LLM-as-a-Judge | Rule-based | Statistical / ML Algorithms | Others
report_methodology='Custom methodology', # Optional: free text description
parameters=[], # Optional: list of report parameters
)
def my_evaluation_report(job: t.Any, data: t.Any, *, cache: dict = {}) -> t.Any:
"""Docstring describing the report purpose."""
# -- BEGIN DEFINITION --
# Your report logic here
# Process data and return metrics
return metrics_dict, processed_data
# Sync to platform
ggx.sync(my_evaluation_report)
Key Points:
- Reports typically work with ReportOutput, DataLogicExample, and AdditionalReportFigure helper components
- Helper components use the
reportparameter to associate with their parent report (e.g.,report='My Evaluation Report') - Report functions typically receive
jobanddataparameters and return processed results - ReportOutput functions generate visualizations (Plotly figures, Pandas DataFrames, or HTML/Markdown strings)
Key Concepts¶
The # -- BEGIN DEFINITION -- Anchor¶
Every component function must include this special comment. Only code after this anchor is synced to the platform.
def my_function():
# Imports and setup code here (NOT synced)
import os
# -- BEGIN DEFINITION --
# Everything after this line IS synced
result = process_data()
return result
Why? This ensures only the core logic is synced, keeping your platform definitions clean and portable.
The cache Parameter¶
All component functions include a cache: dict = {} parameter. This is a reserved keyword that is:
- Automatically removed from function inputs during sync (not exposed to end users)
- Commonly used for storing database connections in RAG implementations
Example from RAG:
if "sql_cursor_obj" not in cache:
conn = sqlite3.connect(...)
cache["sql_cursor_obj"] = conn.cursor()
cursor = cache["sql_cursor_obj"]
Dependency Resolution¶
When you sync a Pipeline, the system:
- Inspects the function bytecode to find referenced objects
- Checks if those objects have
_corridor_metadata - Recursively syncs those dependencies by calling their respective sync handlers
- Collects the version IDs returned from each sync operation
- Includes those version IDs in the pipeline payload (e.g.,
promptVersionIds,foundationModelVersionIds)
Example:
# Define components
import genguardx as ggx
@ggx.Prompt.declare(name='System Prompt')
def system_prompt(*, cache: dict = {}, prompt: str = "You are a helpful assistant."):
"""System instruction for the assistant."""
# -- BEGIN DEFINITION --
return prompt
@ggx.Model.declare(name='GPT-4', provider='openai', model='gpt-4', ownership_type='Proprietary', model_type='LLM')
def gpt4(text: str, *, cache: dict = {}):
"""GPT-4 model wrapper."""
# -- BEGIN DEFINITION --
# Implementation
return {"response": "..."}
@ggx.Pipeline.declare(name='Q&A Pipeline', pipeline_type='Chat based - OpenAI Spec')
def qa_pipeline(
user_message: str,
history: list[t.TypedDict("T", {'role': str, 'content': str}, total=False)] = (),
context: t.Optional[dict[str, str]] = None,
*,
cache: dict = {}
):
"""Q&A pipeline combining prompt and model."""
# -- BEGIN DEFINITION --
prompt = system_prompt()
response = gpt4(f"{prompt}\n{user_message}")
return {"output": response["response"]}
# Sync only the pipeline - dependencies sync automatically
ggx.sync(qa_pipeline)
Independent vs. Pipeline Usage¶
Independent Sync¶
You can declare and sync components without using them in a pipeline:
# Declare a standalone prompt
@ggx.Prompt.declare(name='Greeting Prompt', group='Standalone')
def greeting_prompt(*, cache: dict = {}, prompt: str = "Hello! How can I help you today?"):
"""Greeting message prompt."""
# -- BEGIN DEFINITION --
return prompt
# Sync it independently
ggx.sync(greeting_prompt)
Pipeline Integration¶
Or use components together in a pipeline (they'll sync automatically):
@ggx.Pipeline.declare(name='Greeter Bot', pipeline_type='Chat based - OpenAI Spec')
def greeter_pipeline(
user_message: str,
history: list[t.TypedDict("T", {'role': str, 'content': str}, total=False)] = (),
context: t.Optional[dict[str, str]] = None,
*,
cache: dict = {}
):
"""Simple greeter pipeline."""
# -- BEGIN DEFINITION --
prompt = greeting_prompt() # References the prompt
return {"output": prompt}
ggx.sync(greeter_pipeline) # Syncs both prompt and pipeline
Metadata Parameters Reference¶
Common Parameters (All Components)¶
name(str, optional): Display name on platform. Defaults to function name.group(str, optional): Organizational grouping. Must exist on platform.
Prompt-Specific Parameters¶
task_type(str, optional):'Classification'|'Question Answering'|'Information Extraction'|'Summarization'|'Code Generation'|'Transformation'|'Generation'|'Others'prompt_type(str, optional):'System Instruction'|'User Prompt'|'Others'prompt_elements(list, optional): List of components:['Persona + Goal', 'Tone', 'Task', 'Constraints', 'Context', 'Examples', 'Reasoning Steps', 'Output Format', 'Recap']
Model-Specific Parameters¶
ownership_type(str, optional):'Open Source'|'Proprietary'model_type(str, optional):'LLM'|'Text Embedding'|'Guardrail'|'Judge Model'|'Others'provider(str, optional): Provider identifier (e.g.,'openai','google','anthropic'). If provided, model is treated as API-based.model(str, optional): Specific model identifier (e.g.,'gpt-4','gemini-pro','claude-3-opus'). Required if provider is specified.
RAG-Specific Parameters¶
knowledge_base_format(str, optional):'Vector Database'|'Graph Database'|'Relational Database'|'External Web-Search APIs'|'NoSQL'|'Document'|'Others'provider(str, optional): Provider identifier for API-based RAG systems.
Pipeline-Specific Parameters¶
usecase_type(str, optional):'Question Answering'|'Summarization'|'Translation'task_type(str, optional):'Classification'|'Templated Responses'|'Generative Responses'|'Summarization'|'Others'impact(str, optional):'External Facing'|'Internal Only'|'Internal - with external implications'data_usage(list, optional): List of data types:['No Additional Data', 'General Public Data', 'Internal Policies/Data', 'Customer Specific Data']pipeline_type(str, required):'Chat based - OpenAI Spec'|'Custom Return Type'
Global Function Parameters¶
name(str, optional): Display name on platform. Defaults to function name.group(str, optional): Organizational grouping. Must exist on platform.
Report-Specific Parameters¶
object_types(list, required): List of object types the report evaluates (e.g.,['PIPELINE', 'FOUNDATION_MODEL', 'PROMPT'])name(str, optional): Display name on platform. Defaults to function name.group(str, optional): Organizational grouping. Must exist on platform.risk_type(str, optional):'Accuracy'|'Stability'|'Bias'|'Vulnerability'|'Toxicity'|'Others'task_type(str, optional):'Classification'|'Templated Responses'|'Generative Responses'|'Summarization'|'Others'risk_domain(str, optional):'Model Risk Management'|'Fair Lending'|'Technology'|'Infosec'|'Others'evaluation_methodology(str, optional):'LLM-as-a-Judge'|'Rule-based'|'Statistical / ML Algorithms'|'Others'report_methodology(str, optional): Free-text description of the methodologyparameters(list, optional): List of parameter dictionaries for report execution
Complete Workflow Example¶
import genguardx as ggx
import typing as t
# Step 1: Initialize
ggx.init(
api_url="https://devaisandbox.corridorplatforms.com",
api_key="your-api-key-here",
)
# Step 2: Declare components
@ggx.Prompt.declare(
name='FAQ Prompt',
group='Support',
task_type='Question Answering',
prompt_type='System Instruction',
)
def faq_prompt(*, cache: dict = {}, prompt: str = "Answer FAQs concisely and professionally."):
"""System prompt for FAQ bot."""
# -- BEGIN DEFINITION --
return prompt
@ggx.Model.declare(
name='GPT-3.5',
group='Models',
ownership_type='Proprietary',
model_type='LLM',
provider='openai',
model='gpt-3.5-turbo',
)
def gpt35(text: str, *, cache: dict = {}):
"""GPT-3.5 Turbo model wrapper."""
# -- BEGIN DEFINITION --
# Implementation here
return {"response": "..."}
@ggx.Pipeline.declare(
name='FAQ Bot',
group='Support',
usecase_type='Question Answering',
task_type='Templated Responses',
impact='External Facing',
data_usage=['General Public Data'],
pipeline_type='Chat based - OpenAI Spec',
)
def faq_pipeline(
user_message: str,
history: list[t.TypedDict("T", {'role': str, 'content': str}, total=False)] = (),
context: t.Optional[dict[str, str]] = None,
*,
cache: dict = {}
):
"""Complete FAQ pipeline."""
# -- BEGIN DEFINITION --
prompt = faq_prompt()
response = gpt35(f"{prompt}\n\nQuestion: {user_message}")
return {"output": response["response"]}
# Step 3: Sync (syncs all dependencies automatically)
ggx.sync(faq_pipeline)
Best Practices¶
✅ Do's¶
- Always use the anchor comment:
# -- BEGIN DEFINITION -- - Validate groups exist: Check your platform for valid group names before declaring
- Use type annotations: Help the platform understand your data types
- Test locally first: Run your functions before syncing to catch errors
- Use meaningful names: Choose descriptive names for components
- Include the cache parameter: Even if unused, include
cache: dict = {} - Write clear docstrings: Document what each component does
❌ Don'ts¶
- Don't hardcode secrets: Use environment variables for API keys and passwords
- Don't skip the cache parameter: Required for all component functions
- Don't sync without testing: Ensure functions work locally first
- Don't use undefined groups: Verify group names exist on your platform instance
- Don't forget the anchor comment: Missing anchor will cause sync errors
Troubleshooting¶
"Group not found" Warning¶
Problem: Warning message: ├ [WARN] Group "YourGroupName" not found: Ignoring the group
Cause: The group specified in your declaration doesn't exist on the platform.
Solution:
- Check available groups in your platform UI
- Create the group in platform settings first
- Or remove the
groupparameter (it will default to None or the existing component's group)
Note: This is a warning, not an error - the sync will still complete successfully.
"Expected anchor comment" Error¶
Problem: Error message: AssertionError: Expected anchor comment # -- BEGIN DEFINITION -- to be present in source. Found None
Cause: Your function is missing the required # -- BEGIN DEFINITION -- anchor comment.
Solution: Add the anchor comment before your function's core logic:
import genguardx as ggx
@ggx.Prompt.declare(name='My Prompt')
def my_prompt(*, cache: dict = {}, prompt: str = "Hello"):
"""Docstring here"""
# -- BEGIN DEFINITION -- # <-- Add this line
return prompt
"Skipping X - not declared as a Corridor object" Warning¶
Problem: Warning message: [WARN] Skipping "function_name" - as it is not declared as a Corridor object
Cause: Your pipeline references a function that doesn't have a @declare() decorator.
Solution: Add the appropriate decorator to the referenced function:
import genguardx as ggx
# Before (causes warning)
def helper_function():
return "result"
# After (no warning)
@ggx.Prompt.declare(name='Helper')
def helper_function(*, cache: dict = {}, prompt: str = "result"):
# -- BEGIN DEFINITION --
return prompt
Note: This is a warning - the sync completes, but the dependency won't be tracked or synced.
Invalid Metadata Values Warning¶
Problem: Warning messages like:
├ [WARN] Task Type "YourTaskType" is invalid: Ignoring the Task Type├ [WARN] Prompt Type "YourPromptType" is invalid: Ignoring the Prompt Type
Cause: The value provided for a metadata parameter doesn't match the allowed values.
Solution: Check the Metadata Parameters Reference section above for the exact valid values. For example:
- Task Type must be one of:
'Classification','Question Answering','Information Extraction', etc. - Prompt Type must be one of:
'System Instruction','User Prompt','Others'
Note: This is a warning - the sync completes, but the invalid metadata field is ignored.
"Prompt must be a kwarg named 'prompt'" Error¶
Problem: Error message: ValueError: Prompt "your_prompt_name" must be a kwarg names: "prompt" which contains the prompt template as the default value
Cause: Prompt functions require a specific parameter format.
Solution: Add prompt: str = "your template" as a keyword-only parameter:
import genguardx as ggx
@ggx.Prompt.declare(name='My Prompt')
def my_prompt(*, cache: dict = {}, prompt: str = "Your prompt text here"):
"""Docstring"""
# -- BEGIN DEFINITION --
return prompt
Type Hint Error for dict/list¶
Problem: Error message: Unable to process type hint: '<class 'dict'>' as the dict has no inner type
Cause: Using bare dict or list types without specifying inner types.
Solution: Use proper type hints with inner types:
# Bad
context: dict = None
# Good
context: dict[str, str] = None
context: t.Optional[dict[str, str]] = None
# For lists
history: list = () # Bad
history: list[dict[str, str]] = () # Good
Additional Resources¶
- Platform Documentation: Contact your platform administrator for instance-specific docs
- API Reference: Available in your GenGuardX instance
- Support: Contact your platform administrator or support team