Name | replicantx JSON |
Version |
0.1.4
JSON |
| download |
home_page | None |
Summary | End-to-end testing harness for AI agents via web service API |
upload_time | 2025-07-09 13:39:25 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.11 |
license | None |
keywords |
ai
agent
testing
e2e
api
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# ReplicantX
[](https://www.python.org/downloads/)
[](LICENSE)
**ReplicantX** is an end-to-end testing harness for AI agents that communicates via web service APIs. It enables you to run comprehensive test scenarios against live HTTP APIs with support for multiple authentication methods and detailed reporting.
## β¨ Features
- **Two Test Levels**:
- **Level 1 (Basic)**: Fixed user messages with deterministic assertions
- **Level 2 (Agent)**: Intelligent Replicant agent with configurable facts and conversation goals
- **Pydantic-Based Replicant Agent**: Smart conversational agent that acts like a real user
- **Configurable Facts & Behavior**: Agents can have knowledge (Name, Preferences) and custom personalities
- **Real-time Monitoring**: Watch mode (`--watch`) for live conversation monitoring
- **Technical Debugging**: Debug mode (`--debug`) with detailed HTTP, validation, and AI processing logs
- **Multiple Authentication**: Supabase email+password, custom JWT, or no-auth
- **CLI Interface**: Easy-to-use command-line interface with `replicantx run`
- **Automatic .env Loading**: No manual environment variable sourcing required
- **GitHub Actions Ready**: Built-in workflow for PR testing with Render preview URLs
- **Rich Reporting**: Markdown and JSON reports with timing and assertion results
- **Retry & Backoff**: Robust HTTP client with automatic retry logic
## π Quick Start
### Installation
```bash
pip install replicantx[cli]
```
### Basic Usage
1. Create a test scenario YAML file:
**Basic Scenario (Level 1):**
```yaml
# tests/basic_test.yaml
name: "Test AI Agent Conversation"
base_url: https://your-api.com/api/chat
auth:
provider: noop # or supabase, jwt
level: basic
steps:
- user: "Hello, I need help with booking a flight"
expect_contains: ["flight", "booking"]
- user: "I want to go to Paris"
expect_regex: "(?i)paris.*available"
```
**Agent Scenario (Level 2):**
*Generic Customer Support Example:*
```yaml
# tests/support_test.yaml
name: "Customer Support - Account Issue"
base_url: https://your-api.com/api/support
auth:
provider: noop
level: agent
replicant:
goal: "Get help with account access issue"
facts:
name: "Alex Chen"
email: "alex.chen@example.com"
account_id: "ACC-123456"
issue_type: "login_problem"
last_login: "2 weeks ago"
system_prompt: |
You are a customer seeking help with an account issue. You have the
necessary information but don't provide all details upfront.
Answer questions based on your available facts.
initial_message: "Hi, I'm having trouble accessing my account."
max_turns: 12
completion_keywords: ["resolved", "ticket created", "issue fixed"]
```
*Travel Booking Example:*
```yaml
# tests/travel_test.yaml
name: "Travel Booking - Flight Reservation"
base_url: https://your-api.com/api/chat
auth:
provider: noop
level: agent
replicant:
goal: "Book a business class flight to Paris"
facts:
name: "Sarah Johnson"
email: "sarah@example.com"
travel_class: "business"
destination: "Paris"
budget: "$2000"
system_prompt: |
You are a customer trying to book a flight. You have the
necessary information but don't provide all details upfront.
Answer questions based on your available facts.
initial_message: "Hi, I'd like to book a flight to Paris."
max_turns: 15
completion_keywords: ["booked", "confirmed", "reservation number"]
```
2. Run the test:
```bash
replicantx run tests/my_test.yaml --report report.md
```
3. View the generated report in `report.md`
### π Environment Variables & Configuration
ReplicantX **automatically detects environment variables** from your system, `.env` files, and CI/CD environments. No special configuration needed when installed as a dependency!
#### β
**Automatic Detection**
**When you install ReplicantX in your project:**
```bash
# Your project setup
pip install replicantx[cli]
# Your environment variables (any of these methods work)
export OPENAI_API_KEY=sk-your-key # Shell environment
echo "OPENAI_API_KEY=sk-key" > .env # .env file
# OR set in your CI/CD platform
# ReplicantX automatically finds them!
replicantx run tests/*.yaml
```
#### π **Quick Setup**
**Essential variables for different use cases:**
```bash
# LLM Integration (PydanticAI auto-detects these)
export OPENAI_API_KEY=sk-your-openai-key
export ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
# Supabase Authentication
export SUPABASE_URL=https://your-project.supabase.co
export SUPABASE_ANON_KEY=your-supabase-anon-key
# Target API Configuration
export REPLICANTX_TARGET=your-api-domain.com
# Custom Authentication
export JWT_TOKEN=your-jwt-token
export MY_API_KEY=your-custom-api-key
```
#### π **Works Everywhere**
**Local Development:**
```bash
# Create .env file (ReplicantX automatically loads it!)
cat > .env << 'EOF'
OPENAI_API_KEY=sk-dev-key
REPLICANTX_TARGET=dev-api.example.com
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-supabase-key
EOF
# Just run tests - no need to source .env!
replicantx run tests/*.yaml
# Or export manually (old way still works)
export OPENAI_API_KEY=sk-dev-key
replicantx run tests/*.yaml
```
**GitHub Actions (No .env files needed!):**
```yaml
# .github/workflows/test-api.yml
jobs:
test:
runs-on: ubuntu-latest
env:
# GitHub Secrets β Environment Variables
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
REPLICANTX_TARGET: ${{ secrets.API_TARGET_URL }}
steps:
- run: pip install replicantx[cli]
- run: replicantx run tests/*.yaml --ci
# ReplicantX automatically finds the variables!
```
#### π **Using in YAML Files**
Reference variables with `{{ env.VARIABLE_NAME }}` syntax:
```yaml
name: "API Test"
base_url: "https://{{ env.REPLICANTX_TARGET }}/api/chat"
auth:
provider: supabase
project_url: "{{ env.SUPABASE_URL }}"
api_key: "{{ env.SUPABASE_ANON_KEY }}"
level: agent
replicant:
facts:
api_key: "{{ env.MY_API_KEY }}"
llm:
model: "openai:gpt-4o" # Uses OPENAI_API_KEY automatically
```
#### π― **GitHub Secrets Setup**
1. **Go to** Repository Settings β Secrets and Variables β Actions
2. **Add secrets:**
- `OPENAI_API_KEY` = `sk-your-openai-key`
- `SUPABASE_URL` = `https://your-project.supabase.co`
- `SUPABASE_ANON_KEY` = `your-supabase-key`
- `REPLICANTX_TARGET` = `api.yourproject.com`
3. **Use in workflow:**
```yaml
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
REPLICANTX_TARGET: ${{ secrets.REPLICANTX_TARGET }}
```
**π‘ Key Benefits:**
- β
**Automatic .env loading** - Just create a .env file and run tests
- β
**Zero configuration** - ReplicantX finds variables automatically
- β
**Works everywhere** - local, CI/CD, Docker, cloud platforms
- β
**Secure by default** - no hardcoded secrets in code
- β
**Standard patterns** - uses industry-standard environment variable detection
> **Note**: Create a `.env.example` file in your project to document which variables are needed. See our comprehensive environment variable guide in the [LLM Integration](#-environment-variables) section.
## π― **Automatic .env File Loading**
ReplicantX automatically loads environment variables from `.env` files using python-dotenv. **No manual sourcing required!**
### π **Create .env File**
```bash
# Create .env file in your project root
cat > .env << 'EOF'
# LLM API Keys
OPENAI_API_KEY=sk-your-openai-key
ANTHROPIC_API_KEY=sk-ant-your-anthropic-key
# Target API
REPLICANTX_TARGET=https://api.yourproject.com
# Supabase Authentication
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-supabase-anon-key
TEST_USER_EMAIL=test@example.com
TEST_USER_PASSWORD=testpassword123
# JWT Authentication
JWT_TOKEN=your-jwt-token
EOF
```
### π **Run Tests Directly**
```bash
# Just run - ReplicantX finds .env automatically!
replicantx run tests/*.yaml
# Validate test files
replicantx validate tests/*.yaml
# Generate reports
replicantx run tests/*.yaml --report report.md
```
### π **How It Works**
1. **Automatic Discovery**: ReplicantX looks for `.env` files in current directory and parent directories
2. **Non-intrusive**: If no `.env` file exists, it continues normally
3. **Environment Priority**: Existing environment variables take precedence over `.env` values
4. **Secure**: `.env` files should be added to `.gitignore` to avoid committing secrets
### π‘οΈ **Security Best Practices**
```bash
# Add .env to .gitignore
echo ".env" >> .gitignore
# Create .env.example for documentation
cat > .env.example << 'EOF'
# Copy this file to .env and fill in your values
OPENAI_API_KEY=sk-your-openai-key-here
REPLICANTX_TARGET=https://your-api-domain.com
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-supabase-anon-key-here
EOF
```
**β
No more manual environment variable management!**
## π Documentation
### Test Scenario Configuration
#### Basic Scenarios (Level 1)
Basic scenarios use fixed user messages with deterministic assertions:
```yaml
name: "Basic Test Scenario"
base_url: "https://api.example.com/chat"
auth:
provider: noop
level: basic
steps:
- user: "User message"
expect_contains: ["expected", "text"]
expect_regex: "regex_pattern"
expect_equals: "exact_match"
expect_not_contains: ["forbidden", "text"]
```
#### Agent Scenarios (Level 2)
Agent scenarios use intelligent Replicant agents that converse naturally:
```yaml
name: "Agent Test Scenario"
base_url: "https://api.example.com/chat"
auth:
provider: supabase
email: test@example.com
password: password123
project_url: "{{ env.SUPABASE_URL }}"
api_key: "{{ env.SUPABASE_ANON_KEY }}"
level: agent
validate_politeness: false # Optional: validate conversational tone (default: false)
replicant:
goal: "Description of what the agent should achieve"
facts:
name: "User Name"
email: "user@example.com"
# Add any facts the agent should know
system_prompt: |
Customize the agent's personality and behavior.
This prompt defines how the agent should act.
initial_message: "Starting message for the conversation"
max_turns: 20
completion_keywords:
- "success"
- "completed"
- "finished"
fullconversation: true # Send full conversation history with each request
```
#### Politeness Validation
By default, ReplicantX focuses on functional API validation. However, you can optionally enable politeness/conversational tone validation:
```yaml
# Disable politeness validation (default) - focuses on functional responses
validate_politeness: false
# Enable politeness validation - also checks for conversational tone
validate_politeness: true
```
**When to use politeness validation:**
- β
**Customer-facing APIs** where tone matters
- β
**Chatbots and conversational AI** services
- β
**User experience testing** scenarios
**When to skip politeness validation:**
- β **Internal APIs** focused on functionality
- β **Data APIs** returning structured responses
- β **Technical integrations** where tone is irrelevant
**Note:** Politeness validation is subjective and based on common conversational patterns. It looks for polite phrases like "please", "thank you", "how can I help", question patterns, and helpful language.
### CLI Commands
```bash
# Run all tests in a directory
replicantx run tests/*.yaml --report report.md
# Run with CI mode (exits 1 on failure)
replicantx run tests/*.yaml --report report.md --ci
# Run specific test file
replicantx run tests/specific_test.yaml
# Real-time conversation monitoring
replicantx run tests/*.yaml --watch
# Technical debugging with detailed logs
replicantx run tests/*.yaml --debug
# Combined monitoring and debugging
replicantx run tests/*.yaml --debug --watch
# Validate test files without running
replicantx validate tests/*.yaml --verbose
```
### π Real-time Monitoring & Debugging
ReplicantX provides comprehensive monitoring and debugging capabilities to help you understand what's happening during test execution.
#### π **Watch Mode (`--watch`)**
Real-time conversation monitoring for observing test execution as it happens:
```bash
replicantx run tests/agent_test.yaml --watch
```
**What you see:**
- π₯ **Live conversation setup** with goal and facts
- π€ **Replicant messages** as they're sent (with timestamps)
- β±οΈ **Response waiting indicators**
- π€ **Agent responses** as received
- β
/β **Step results** with pass/fail status and timing
- π **Final summary** with success rate, duration, goal achievement
**Perfect for:**
- β
**Live demos** - Show clients real AI conversations
- β
**Test monitoring** - Watch long-running tests progress
- β
**User experience validation** - See conversation flow
- β
**Performance monitoring** - Track response times
**Example Output:**
```
[22:04:42] π₯ LIVE CONVERSATION - Starting agent scenario
[22:04:42] π― Goal: Book a business class flight to Paris
[22:04:42] π€ Replicant: Hi, I'd like to book a flight to Paris.
[22:04:52] β
Step 1: PASSED (10.2s)
[22:04:52] π€ Agent: What cabin class would you prefer?
[22:04:53] π€ Replicant: Business class, please.
[22:05:03] β
Step 2: PASSED (9.8s)
```
#### π§ **Debug Mode (`--debug`)**
Technical deep-dive with detailed system information:
```bash
replicantx run tests/agent_test.yaml --debug
```
**What you see:**
- π **HTTP client setup** (URL, timeout, auth provider, headers)
- π **Replicant agent initialization** (goal, facts, AI model settings)
- π **HTTP requests** (payload details, conversation history)
- π **API responses** (status codes, latency, content preview)
- π **Response validation** (assertion counts, individual results)
- π **AI processing** (response parsing, message generation)
**Perfect for:**
- π **Troubleshooting** - Diagnose failed assertions
- π **Performance tuning** - Analyze HTTP latency and bottlenecks
- π **Integration debugging** - Check payload formats and API calls
- π **AI behavior analysis** - Understand PydanticAI decision making
**Example Output:**
```
π DEBUG HTTP Client initialized
ββ base_url: https://api.example.com/chat
ββ timeout: 120s
ββ auth_provider: supabase
ββ auth_headers: 2 headers
π DEBUG HTTP request payload
ββ message: Hi, I'd like to book a flight to Paris.
ββ conversation_history_length: 1
ββ payload_size: 229 chars
π DEBUG Response validation completed
ββ total_assertions: 2
ββ passed_assertions: 2
ββ overall_passed: True
```
#### π― **Combined Mode (`--debug --watch`)**
Get both real-time conversation flow and technical details:
```bash
replicantx run tests/agent_test.yaml --debug --watch
```
**Perfect for:**
- π― **Development** - Full visibility during feature building
- π― **Complex debugging** - When you need everything
- π― **Training** - Teaching others how the system works
- π― **Comprehensive analysis** - Complete test execution insight
#### π‘ **Monitoring Tips**
**For Long-running Tests:**
```bash
# Watch progress while generating a report
replicantx run tests/*.yaml --watch --report detailed.md
```
**For CI/CD Debugging:**
```bash
# Debug mode with CI exit codes
replicantx run tests/*.yaml --debug --ci
```
**For Performance Analysis:**
```bash
# Combined with verbose output
replicantx run tests/*.yaml --debug --verbose --report performance.json
```
### Authentication Providers
#### Supabase
```yaml
auth:
provider: supabase
email: user@example.com
password: password123
project_url: "{{ env.SUPABASE_URL }}"
api_key: "{{ env.SUPABASE_ANON_KEY }}"
```
#### JWT
```yaml
auth:
provider: jwt
token: "{{ env.JWT_TOKEN }}"
```
#### No Authentication
```yaml
auth:
provider: noop
```
## π€ Replicant Agent System
The Replicant agent is a Pydantic-based intelligent conversational agent that:
### Key Features
- **Fact-Based Responses**: Uses configured facts to answer API questions intelligently
- **Natural Conversation**: Acts like a real user who doesn't provide all information upfront
- **Customizable Behavior**: System prompts allow different personalities and response patterns
- **Goal-Oriented**: Works toward specific objectives with completion detection
- **Context Awareness**: Maintains conversation history and state
### LLM-Powered Fact Usage
The agent intelligently uses configured facts through LLM integration:
- **Context-aware**: LLMs understand when facts are relevant to questions
- **Natural integration**: Facts are woven naturally into conversation responses
- **Smart timing**: Agent knows when to volunteer information vs. wait to be asked
- **Conversation memory**: Recent chat history provides context for fact usage
### Conversation State Management
ReplicantX provides flexible conversation state management to handle different API architectures:
#### Full Conversation History (`fullconversation: true`)
Sends the complete conversation history (including all responses) with each request:
```yaml
replicant:
fullconversation: true # Default behavior
```
**Benefits:**
- β
**Complete Context**: API receives full conversation state
- β
**Stateless APIs**: Works with APIs that don't maintain session state
- β
**Microservices**: Suitable for distributed systems
- β
**Testing Realism**: Mimics real-world stateless interactions
#### Limited History (`fullconversation: false`)
Sends only the last 10 messages for performance:
```yaml
replicant:
fullconversation: false
```
**Use Cases:**
- π§ **Performance Testing**: Reduce payload size for high-volume testing
- π§ **Legacy APIs**: Compatible with APIs expecting limited context
- π§ **Memory Constraints**: When API has payload size limitations
### API Payload Format Configuration
ReplicantX supports multiple API payload formats for maximum compatibility with any conversational API:
#### OpenAI Format (`payload_format: openai`) - **Default**
Industry-standard OpenAI chat completion format:
```yaml
replicant:
payload_format: openai # Default behavior
```
**Payload Structure:**
```json
{
"messages": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there!"},
{"role": "user", "content": "How are you?"}
]
}
```
**Best For:**
- β
**OpenAI APIs** and compatible services
- β
**Industry standard** - widely supported
- β
**Full conversation context** with message arrays
- β
**Modern conversational AI** platforms
#### Simple Format (`payload_format: simple`)
Minimal message-only format for basic APIs:
```yaml
replicant:
payload_format: simple
```
**Payload Structure:**
```json
{
"message": "Hello, how are you?"
}
```
**Best For:**
- β
**Simple APIs** that only need the current message
- β
**Performance-critical** scenarios
- β
**Legacy systems** with minimal payload requirements
- β
**Testing basic functionality** without conversation context
#### Anthropic Format (`payload_format: anthropic`)
Anthropic Claude-compatible format:
```yaml
replicant:
payload_format: anthropic
```
**Payload Structure:**
```json
{
"messages": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there!"}
]
}
```
**Best For:**
- β
**Anthropic Claude APIs** and compatible services
- β
**Claude-based applications** and integrations
- β
**Conversational AI** platforms using Claude models
#### Legacy Format (`payload_format: legacy`)
Original ReplicantX format for backward compatibility:
```yaml
replicant:
payload_format: legacy
```
**Payload Structure:**
```json
{
"message": "Hello, how are you?",
"timestamp": "2025-07-09T10:30:00",
"conversation_history": [
{"role": "user", "content": "Hello"},
{"role": "assistant", "content": "Hi there!"}
]
}
```
**Best For:**
- π§ **Existing ReplicantX integrations** (backward compatibility)
- π§ **Custom APIs** expecting the original format
- π§ **Migration scenarios** when transitioning to new formats
#### Session Management
ReplicantX supports session management to maintain conversation state across multiple API requests without sending the full conversation history each time. This is more efficient and realistic for production APIs.
##### Session Modes
```yaml
replicant:
# Session management configuration
session_mode: auto # disabled, auto, fixed, or env
session_id: null # Required when session_mode is "fixed"
session_timeout: 300 # Session timeout in seconds (default: 5 minutes)
session_format: uuid # replicantx or uuid (default: uuid)
session_placement: body # header, body, or url (default: body)
session_variable_name: session_id # Custom name for session variable
```
**Session Modes:**
- `disabled` (default): No session management, uses full conversation history
- `auto`: Auto-generate unique session ID for each test run
- `fixed`: Use a specific session ID (requires `session_id` field)
- `env`: Use session ID from `REPLICANTX_SESSION_ID` environment variable
**Session Formats:**
- `uuid` (default): Standard UUID format (e.g., `550e8400-e29b-41d4-a716-446655440000`)
- `replicantx`: ReplicantX format (e.g., `replicantx_c8ff856c`)
**Session Placement:**
- `body` (default): Session ID in request body/payload
- `header`: Session ID in HTTP headers
- `url`: Session ID in URL path (RESTful)
**Session Variable Name:**
- Custom name for the session variable in headers or body
- Examples: `session_id`, `conversation_id`, `x-conversation-id`, `chat_id`
**Session-Aware Payload Formats:**
- `openai_session`: OpenAI-compatible with session support
- `simple_session`: Simple format with session support
- `restful_session`: RESTful format with session support
##### Example Configurations
**Auto-Generated UUID Session (Recommended):**
```yaml
replicant:
session_mode: auto
session_format: uuid # Standard UUID format
session_placement: body
session_variable_name: session_id
payload_format: openai_session
fullconversation: false
session_timeout: 600 # 10 minutes
```
**ReplicantX Format with Header:**
```yaml
replicant:
session_mode: auto
session_format: replicantx # ReplicantX format
session_placement: header
session_variable_name: x-conversation-id
payload_format: openai_session
fullconversation: false
```
**Fixed Session ID with Custom Variable:**
```yaml
replicant:
session_mode: fixed
session_id: "test_session_12345"
session_format: uuid
session_placement: body
session_variable_name: conversation_id
payload_format: simple_session
fullconversation: false
```
**RESTful Session (Session ID in URL):**
```yaml
replicant:
session_mode: auto
session_format: uuid
session_placement: url
payload_format: restful_session
fullconversation: false
# Results in requests to: /conversations/{session_id}/messages
```
**Environment-Based Session with Header:**
```bash
# Set environment variable
export REPLICANTX_SESSION_ID="prod_session_abc123"
# Use in YAML
replicant:
session_mode: env
session_format: uuid
session_placement: header
session_variable_name: x-chat-id
payload_format: openai_session
fullconversation: false
```
##### Session Management Benefits
**β
Efficiency:**
- Reduces payload size significantly
- Faster API requests
- Lower bandwidth usage
**β
Realistic Testing:**
- Matches production API patterns
- Tests session handling logic
- Validates conversation continuity
**β
Flexibility:**
- Multiple session ID strategies
- Configurable timeouts
- Different payload formats
**β
Debugging:**
- Session information in debug logs
- Session lifecycle tracking
- Timeout monitoring
##### When to Use Session Management
**Use session management when:**
- β
Your API supports conversation IDs
- β
You want to test session handling
- β
Payload size is a concern
- β
Testing production-like scenarios
**Use full conversation when:**
- β API doesn't support sessions
- β Testing legacy endpoints
- β Need complete conversation context
- β Debugging conversation flow
### Complete Configuration Example
```yaml
name: "Universal API Test"
base_url: https://api.example.com/chat
auth:
provider: noop
level: agent
replicant:
goal: "Test API with OpenAI-compatible format"
facts:
name: "Test User"
email: "test@example.com"
system_prompt: |
You are a helpful user testing an API.
initial_message: "Hello, I'm testing the API."
max_turns: 10
completion_keywords: ["complete", "finished", "done"]
fullconversation: true # Send full conversation history
payload_format: openai # Use OpenAI-compatible format
llm:
model: "test"
temperature: 0.7
max_tokens: 150
```
### Session Management Examples
**UUID Format with Header (Recommended for APIs):**
```yaml
name: "Flight Booking with UUID Header"
base_url: "https://api.example.com/chat"
auth:
provider: "noop"
level: "agent"
replicant:
goal: "Book a flight from London to Paris"
facts:
name: "Alex Johnson"
email: "alex@example.com"
departure: "London"
destination: "Paris"
date: "next Friday"
system_prompt: "You are a customer booking a flight. Be polite and provide details when asked."
initial_message: "Hi, I need to book a flight from London to Paris for next Friday."
max_turns: 15
session_mode: auto
session_format: uuid # Standard UUID format
session_placement: header # In HTTP headers
session_variable_name: x-conversation-id # Custom header name
payload_format: openai_session
fullconversation: false
session_timeout: 600
llm:
model: "test"
```
**ReplicantX Format with Body:**
```yaml
name: "Customer Support with ReplicantX Body"
base_url: "https://api.example.com/support"
auth:
provider: "noop"
level: "agent"
replicant:
goal: "Get help with billing issue"
facts:
name: "Sarah Chen"
account_id: "ACC-789456"
issue: "billing"
system_prompt: "You are a customer with a billing question."
initial_message: "Hello, I have a billing question."
max_turns: 10
session_mode: auto
session_format: replicantx # ReplicantX format
session_placement: body # In request body
session_variable_name: conversation_id # Custom variable name
payload_format: simple_session
fullconversation: false
session_timeout: 300
llm:
model: "test"
```
**UUID Format with URL (RESTful):**
```yaml
name: "Pizza Order with UUID URL"
base_url: "https://api.example.com"
auth:
provider: "noop"
level: "agent"
replicant:
goal: "Order a pizza for delivery"
facts:
name: "Mike Rodriguez"
address: "123 Main St, NYC"
phone: "+1 555 123 4567"
system_prompt: "You are ordering a pizza. Be friendly and provide your details."
initial_message: "Hi, I'd like to order a pizza for delivery."
max_turns: 8
session_mode: auto
session_format: uuid # UUID format
session_placement: url # In URL path
payload_format: restful_session
fullconversation: false
# Results in requests to: /conversations/{uuid}/messages
llm:
model: "test"
```
### Migration Guide
**From Legacy to OpenAI Format:**
```yaml
# Old configuration (still works)
replicant:
payload_format: legacy # or omit entirely
# New recommended configuration
replicant:
payload_format: openai # More compatible with modern APIs
```
**For Simple APIs:**
```yaml
replicant:
payload_format: simple
fullconversation: false # Not needed for simple format
```
**For Anthropic APIs:**
```yaml
replicant:
payload_format: anthropic
fullconversation: true # Maintain conversation context
```
### System Prompt Examples
**Helpful User:**
```yaml
system_prompt: |
You are a polite user trying to achieve your goal. You have the
necessary information but need prompting to remember details.
```
**Forgetful Customer:**
```yaml
system_prompt: |
You are a customer who sometimes forgets details and needs
multiple prompts. You're friendly but can be a bit scattered.
```
**Demanding User:**
```yaml
system_prompt: |
You are an impatient user who wants quick results. You provide
information when asked but expect efficient service.
```
## π§ LLM Integration
ReplicantX uses **PydanticAI** for powerful LLM integration with multiple providers:
### Supported Providers
- **OpenAI**: GPT-4, GPT-4o, and other OpenAI models
- **Anthropic**: Claude 4.0 Sonnet, Claude 4 Haiku, and other Claude models
- **Google**: Gemini models via Google AI and VertexAI
- **Groq**: Fast inference with Llama, Mixtral, and other models
- **Ollama**: Local LLM deployment
- **Test**: Built-in test model for development (no API keys needed)
### Configuration
Add LLM configuration to your agent scenarios using PydanticAI model strings:
*Technical Support Example:*
```yaml
level: agent
replicant:
goal: "Get technical support for my account"
facts:
name: "Jordan Smith"
# ... other facts
system_prompt: |
You are a customer seeking help with a technical issue.
Use your available facts to answer questions naturally.
# ... other config
llm:
model: "openai:gpt-4.1-mini" # PydanticAI model string
temperature: 0.7 # Response creativity (0.0-1.0)
max_tokens: 150 # Maximum response length
```
*Flight Booking Example:*
```yaml
level: agent
replicant:
goal: "Book a business class flight to Paris"
facts:
name: "Sarah Johnson"
destination: "Paris"
travel_class: "business"
# ... other facts
system_prompt: |
You are a customer trying to book a flight. You have the
necessary information but don't provide all details upfront.
# ... other config
llm:
model: "anthropic:claude-3-5-sonnet-latest" # PydanticAI model string
temperature: 0.8 # Response creativity (0.0-1.0)
max_tokens: 200 # Maximum response length
```
### Model String Examples
```yaml
# OpenAI models
model: "openai:gpt-4o"
model: "openai:gpt-4.1-mini"
model: "openai:gpt-4.1-nano"
# Anthropic models
model: "anthropic:claude-3-5-sonnet-latest"
model: "anthropic:claude-3-haiku-20240307"
# Google models
model: "gemini-1.5-pro"
model: "gemini-1.5-flash"
# Groq models
model: "groq:llama-3.1-8b-instant"
model: "groq:mixtral-8x7b-32768"
# Test model (no API key needed)
model: "test"
```
### Environment Variables
PydanticAI automatically detects API keys from environment variables:
```bash
# OpenAI
export OPENAI_API_KEY=sk-your-api-key
# Anthropic
export ANTHROPIC_API_KEY=sk-ant-your-api-key
# Google AI
export GOOGLE_API_KEY=your-google-api-key
# Groq
export GROQ_API_KEY=your-groq-api-key
```
### Installation with LLM Support
```bash
# Install with all LLM providers
pip install replicantx[all]
# Install with specific providers
pip install replicantx[openai]
pip install replicantx[anthropic]
# Core installation (includes PydanticAI with test model)
pip install replicantx
```
### How LLM Integration Works
1. **Smart Prompting**: System prompts are enhanced with available facts and conversation context
2. **Natural Responses**: LLMs generate contextually appropriate responses based on user personas
3. **Fact Integration**: Available facts are automatically included in prompts for relevant responses
4. **Graceful Fallback**: If LLM calls fail, the system falls back to rule-based responses
5. **Conversation Memory**: Recent conversation history is maintained for context
### Examples with PydanticAI
*Customer Support Example:*
```yaml
name: "Customer Support - Billing Issue"
base_url: https://api.example.com/support
auth:
provider: noop
level: agent
replicant:
goal: "Get customer support for billing issue"
facts:
name: "Alex Chen"
account_number: "ACC-12345"
issue_type: "billing"
last_payment: "$99.99 on Jan 15th"
system_prompt: |
You are a customer who is polite but slightly frustrated about
a billing issue. You have the necessary account information but
may need prompting to remember specific details.
initial_message: "Hi, I have a question about my recent bill."
max_turns: 12
completion_keywords: ["resolved", "ticket created", "issue closed"]
fullconversation: true # Send full conversation history with each request
payload_format: openai # Use OpenAI-compatible format
llm:
model: "openai:gpt-4o" # PydanticAI model string
temperature: 0.8
max_tokens: 120
```
*Flight Booking Example:*
```yaml
name: "Travel Booking - Flight to Paris"
base_url: https://api.example.com/chat
auth:
provider: supabase
project_url: "{{ env.SUPABASE_URL }}"
api_key: "{{ env.SUPABASE_ANON_KEY }}"
email: "{{ env.TEST_USER_EMAIL }}"
password: "{{ env.TEST_USER_PASSWORD }}"
level: agent
replicant:
goal: "Book a business class flight to Paris for next weekend"
facts:
name: "Sarah Johnson"
email: "sarah.johnson@example.com"
travel_class: "business"
destination: "Paris"
departure_city: "New York"
travel_date: "next Friday"
passengers: 1
budget: "$3000"
preferences: "aisle seat, vegetarian meal"
system_prompt: |
You are a helpful user trying to book a flight. You have all the
necessary information but you're a typical user who doesn't
provide all details upfront.
initial_message: "Hi, I'd like to book a flight to Paris for next weekend."
max_turns: 15
completion_keywords: ["booked", "confirmed", "reservation number", "booking complete"]
fullconversation: true # Send full conversation history with each request
payload_format: openai # Use OpenAI-compatible format
llm:
model: "openai:gpt-4o"
temperature: 0.7
max_tokens: 150
```
These examples enable much more natural and contextually aware conversations compared to rule-based responses.
## π§ GitHub Actions Integration
Add this workflow to `.github/workflows/replicantx.yml`:
```yaml
name: ReplicantX E2E Tests
on:
pull_request: { types: [opened, synchronize, reopened] }
jobs:
replicantx:
runs-on: ubuntu-latest
env:
SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
REPLICANTX_TARGET: pr-${{ github.event.pull_request.number }}-helix-api.onrender.com
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.11" }
- run: pip install "replicantx[cli]"
- run: |
until curl -sf "https://$REPLICANTX_TARGET/health"; do
echo "Waiting for previewβ¦"; sleep 5; done
- run: replicantx run tests/*.yaml --report report.md --ci
- uses: marocchino/sticky-pull-request-comment@v2
if: always()
with: { path: report.md }
```
Raw data
{
"_id": null,
"home_page": null,
"name": "replicantx",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "ai, agent, testing, e2e, api",
"author": null,
"author_email": "Helix Technologies Limited <team@replicantx.org>",
"download_url": "https://files.pythonhosted.org/packages/e5/8b/064b17ef9f66d7e6a0ebe01ecda9a21ba6779ad043a149bde7a7bc2d0419/replicantx-0.1.4.tar.gz",
"platform": null,
"description": "# ReplicantX\n\n[](https://www.python.org/downloads/)\n[](LICENSE)\n\n**ReplicantX** is an end-to-end testing harness for AI agents that communicates via web service APIs. It enables you to run comprehensive test scenarios against live HTTP APIs with support for multiple authentication methods and detailed reporting.\n\n## \u2728 Features\n\n- **Two Test Levels**: \n - **Level 1 (Basic)**: Fixed user messages with deterministic assertions\n - **Level 2 (Agent)**: Intelligent Replicant agent with configurable facts and conversation goals\n- **Pydantic-Based Replicant Agent**: Smart conversational agent that acts like a real user\n- **Configurable Facts & Behavior**: Agents can have knowledge (Name, Preferences) and custom personalities\n- **Real-time Monitoring**: Watch mode (`--watch`) for live conversation monitoring\n- **Technical Debugging**: Debug mode (`--debug`) with detailed HTTP, validation, and AI processing logs\n- **Multiple Authentication**: Supabase email+password, custom JWT, or no-auth\n- **CLI Interface**: Easy-to-use command-line interface with `replicantx run`\n- **Automatic .env Loading**: No manual environment variable sourcing required\n- **GitHub Actions Ready**: Built-in workflow for PR testing with Render preview URLs\n- **Rich Reporting**: Markdown and JSON reports with timing and assertion results\n- **Retry & Backoff**: Robust HTTP client with automatic retry logic\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n```bash\npip install replicantx[cli]\n```\n\n### Basic Usage\n\n1. Create a test scenario YAML file:\n\n**Basic Scenario (Level 1):**\n```yaml\n# tests/basic_test.yaml\nname: \"Test AI Agent Conversation\"\nbase_url: https://your-api.com/api/chat\nauth:\n provider: noop # or supabase, jwt\nlevel: basic\nsteps:\n - user: \"Hello, I need help with booking a flight\"\n expect_contains: [\"flight\", \"booking\"]\n - user: \"I want to go to Paris\"\n expect_regex: \"(?i)paris.*available\"\n```\n\n**Agent Scenario (Level 2):**\n\n*Generic Customer Support Example:*\n```yaml\n# tests/support_test.yaml\nname: \"Customer Support - Account Issue\"\nbase_url: https://your-api.com/api/support\nauth:\n provider: noop\nlevel: agent\nreplicant:\n goal: \"Get help with account access issue\"\n facts:\n name: \"Alex Chen\"\n email: \"alex.chen@example.com\"\n account_id: \"ACC-123456\"\n issue_type: \"login_problem\"\n last_login: \"2 weeks ago\"\n system_prompt: |\n You are a customer seeking help with an account issue. You have the \n necessary information but don't provide all details upfront.\n Answer questions based on your available facts.\n initial_message: \"Hi, I'm having trouble accessing my account.\"\n max_turns: 12\n completion_keywords: [\"resolved\", \"ticket created\", \"issue fixed\"]\n```\n\n*Travel Booking Example:*\n```yaml\n# tests/travel_test.yaml\nname: \"Travel Booking - Flight Reservation\"\nbase_url: https://your-api.com/api/chat\nauth:\n provider: noop\nlevel: agent\nreplicant:\n goal: \"Book a business class flight to Paris\"\n facts:\n name: \"Sarah Johnson\"\n email: \"sarah@example.com\"\n travel_class: \"business\"\n destination: \"Paris\"\n budget: \"$2000\"\n system_prompt: |\n You are a customer trying to book a flight. You have the \n necessary information but don't provide all details upfront.\n Answer questions based on your available facts.\n initial_message: \"Hi, I'd like to book a flight to Paris.\"\n max_turns: 15\n completion_keywords: [\"booked\", \"confirmed\", \"reservation number\"]\n```\n\n2. Run the test:\n\n```bash\nreplicantx run tests/my_test.yaml --report report.md\n```\n\n3. View the generated report in `report.md`\n\n### \ud83d\udd10 Environment Variables & Configuration\n\nReplicantX **automatically detects environment variables** from your system, `.env` files, and CI/CD environments. No special configuration needed when installed as a dependency!\n\n#### \u2705 **Automatic Detection**\n\n**When you install ReplicantX in your project:**\n```bash\n# Your project setup\npip install replicantx[cli]\n\n# Your environment variables (any of these methods work)\nexport OPENAI_API_KEY=sk-your-key # Shell environment\necho \"OPENAI_API_KEY=sk-key\" > .env # .env file\n# OR set in your CI/CD platform\n\n# ReplicantX automatically finds them!\nreplicantx run tests/*.yaml\n```\n\n#### \ud83d\ude80 **Quick Setup**\n\n**Essential variables for different use cases:**\n\n```bash\n# LLM Integration (PydanticAI auto-detects these)\nexport OPENAI_API_KEY=sk-your-openai-key\nexport ANTHROPIC_API_KEY=sk-ant-your-anthropic-key\n\n# Supabase Authentication\nexport SUPABASE_URL=https://your-project.supabase.co\nexport SUPABASE_ANON_KEY=your-supabase-anon-key\n\n# Target API Configuration\nexport REPLICANTX_TARGET=your-api-domain.com\n\n# Custom Authentication\nexport JWT_TOKEN=your-jwt-token\nexport MY_API_KEY=your-custom-api-key\n```\n\n#### \ud83d\udd04 **Works Everywhere**\n\n**Local Development:**\n```bash\n# Create .env file (ReplicantX automatically loads it!)\ncat > .env << 'EOF'\nOPENAI_API_KEY=sk-dev-key\nREPLICANTX_TARGET=dev-api.example.com\nSUPABASE_URL=https://your-project.supabase.co\nSUPABASE_ANON_KEY=your-supabase-key\nEOF\n\n# Just run tests - no need to source .env!\nreplicantx run tests/*.yaml\n\n# Or export manually (old way still works)\nexport OPENAI_API_KEY=sk-dev-key\nreplicantx run tests/*.yaml\n```\n\n**GitHub Actions (No .env files needed!):**\n```yaml\n# .github/workflows/test-api.yml\njobs:\n test:\n runs-on: ubuntu-latest\n env:\n # GitHub Secrets \u2192 Environment Variables\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n REPLICANTX_TARGET: ${{ secrets.API_TARGET_URL }}\n steps:\n - run: pip install replicantx[cli]\n - run: replicantx run tests/*.yaml --ci\n # ReplicantX automatically finds the variables!\n```\n\n#### \ud83d\udcdd **Using in YAML Files**\n\nReference variables with `{{ env.VARIABLE_NAME }}` syntax:\n\n```yaml\nname: \"API Test\"\nbase_url: \"https://{{ env.REPLICANTX_TARGET }}/api/chat\"\nauth:\n provider: supabase\n project_url: \"{{ env.SUPABASE_URL }}\"\n api_key: \"{{ env.SUPABASE_ANON_KEY }}\"\nlevel: agent\nreplicant:\n facts:\n api_key: \"{{ env.MY_API_KEY }}\"\n llm:\n model: \"openai:gpt-4o\" # Uses OPENAI_API_KEY automatically\n```\n\n#### \ud83c\udfaf **GitHub Secrets Setup**\n\n1. **Go to** Repository Settings \u2192 Secrets and Variables \u2192 Actions\n2. **Add secrets:**\n - `OPENAI_API_KEY` = `sk-your-openai-key`\n - `SUPABASE_URL` = `https://your-project.supabase.co`\n - `SUPABASE_ANON_KEY` = `your-supabase-key`\n - `REPLICANTX_TARGET` = `api.yourproject.com`\n\n3. **Use in workflow:**\n ```yaml\n env:\n OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}\n REPLICANTX_TARGET: ${{ secrets.REPLICANTX_TARGET }}\n ```\n\n**\ud83d\udca1 Key Benefits:**\n- \u2705 **Automatic .env loading** - Just create a .env file and run tests\n- \u2705 **Zero configuration** - ReplicantX finds variables automatically\n- \u2705 **Works everywhere** - local, CI/CD, Docker, cloud platforms\n- \u2705 **Secure by default** - no hardcoded secrets in code\n- \u2705 **Standard patterns** - uses industry-standard environment variable detection\n\n> **Note**: Create a `.env.example` file in your project to document which variables are needed. See our comprehensive environment variable guide in the [LLM Integration](#-environment-variables) section.\n\n## \ud83c\udfaf **Automatic .env File Loading**\n\nReplicantX automatically loads environment variables from `.env` files using python-dotenv. **No manual sourcing required!**\n\n### \ud83d\udcc1 **Create .env File**\n\n```bash\n# Create .env file in your project root\ncat > .env << 'EOF'\n# LLM API Keys\nOPENAI_API_KEY=sk-your-openai-key\nANTHROPIC_API_KEY=sk-ant-your-anthropic-key\n\n# Target API\nREPLICANTX_TARGET=https://api.yourproject.com\n\n# Supabase Authentication\nSUPABASE_URL=https://your-project.supabase.co\nSUPABASE_ANON_KEY=your-supabase-anon-key\nTEST_USER_EMAIL=test@example.com\nTEST_USER_PASSWORD=testpassword123\n\n# JWT Authentication\nJWT_TOKEN=your-jwt-token\nEOF\n```\n\n### \ud83d\ude80 **Run Tests Directly**\n\n```bash\n# Just run - ReplicantX finds .env automatically!\nreplicantx run tests/*.yaml\n\n# Validate test files\nreplicantx validate tests/*.yaml\n\n# Generate reports\nreplicantx run tests/*.yaml --report report.md\n```\n\n### \ud83d\udd0d **How It Works**\n\n1. **Automatic Discovery**: ReplicantX looks for `.env` files in current directory and parent directories\n2. **Non-intrusive**: If no `.env` file exists, it continues normally\n3. **Environment Priority**: Existing environment variables take precedence over `.env` values\n4. **Secure**: `.env` files should be added to `.gitignore` to avoid committing secrets\n\n### \ud83d\udee1\ufe0f **Security Best Practices**\n\n```bash\n# Add .env to .gitignore\necho \".env\" >> .gitignore\n\n# Create .env.example for documentation\ncat > .env.example << 'EOF'\n# Copy this file to .env and fill in your values\nOPENAI_API_KEY=sk-your-openai-key-here\nREPLICANTX_TARGET=https://your-api-domain.com\nSUPABASE_URL=https://your-project.supabase.co\nSUPABASE_ANON_KEY=your-supabase-anon-key-here\nEOF\n```\n\n**\u2705 No more manual environment variable management!**\n\n## \ud83d\udcd6 Documentation\n\n### Test Scenario Configuration\n\n#### Basic Scenarios (Level 1)\n\nBasic scenarios use fixed user messages with deterministic assertions:\n\n```yaml\nname: \"Basic Test Scenario\"\nbase_url: \"https://api.example.com/chat\"\nauth:\n provider: noop\nlevel: basic\nsteps:\n - user: \"User message\"\n expect_contains: [\"expected\", \"text\"]\n expect_regex: \"regex_pattern\"\n expect_equals: \"exact_match\"\n expect_not_contains: [\"forbidden\", \"text\"]\n```\n\n#### Agent Scenarios (Level 2)\n\nAgent scenarios use intelligent Replicant agents that converse naturally:\n\n```yaml\nname: \"Agent Test Scenario\"\nbase_url: \"https://api.example.com/chat\"\nauth:\n provider: supabase\n email: test@example.com\n password: password123\n project_url: \"{{ env.SUPABASE_URL }}\"\n api_key: \"{{ env.SUPABASE_ANON_KEY }}\"\nlevel: agent\nvalidate_politeness: false # Optional: validate conversational tone (default: false)\nreplicant:\n goal: \"Description of what the agent should achieve\"\n facts:\n name: \"User Name\"\n email: \"user@example.com\"\n # Add any facts the agent should know\n system_prompt: |\n Customize the agent's personality and behavior.\n This prompt defines how the agent should act.\n initial_message: \"Starting message for the conversation\"\n max_turns: 20\n completion_keywords: \n - \"success\"\n - \"completed\"\n - \"finished\"\n fullconversation: true # Send full conversation history with each request\n```\n\n#### Politeness Validation\n\nBy default, ReplicantX focuses on functional API validation. However, you can optionally enable politeness/conversational tone validation:\n\n```yaml\n# Disable politeness validation (default) - focuses on functional responses\nvalidate_politeness: false\n\n# Enable politeness validation - also checks for conversational tone\nvalidate_politeness: true\n```\n\n**When to use politeness validation:**\n- \u2705 **Customer-facing APIs** where tone matters\n- \u2705 **Chatbots and conversational AI** services\n- \u2705 **User experience testing** scenarios\n\n**When to skip politeness validation:**\n- \u274c **Internal APIs** focused on functionality\n- \u274c **Data APIs** returning structured responses\n- \u274c **Technical integrations** where tone is irrelevant\n\n**Note:** Politeness validation is subjective and based on common conversational patterns. It looks for polite phrases like \"please\", \"thank you\", \"how can I help\", question patterns, and helpful language.\n\n### CLI Commands\n\n```bash\n# Run all tests in a directory\nreplicantx run tests/*.yaml --report report.md\n\n# Run with CI mode (exits 1 on failure)\nreplicantx run tests/*.yaml --report report.md --ci\n\n# Run specific test file\nreplicantx run tests/specific_test.yaml\n\n# Real-time conversation monitoring\nreplicantx run tests/*.yaml --watch\n\n# Technical debugging with detailed logs\nreplicantx run tests/*.yaml --debug\n\n# Combined monitoring and debugging\nreplicantx run tests/*.yaml --debug --watch\n\n# Validate test files without running\nreplicantx validate tests/*.yaml --verbose\n```\n\n### \ud83d\udcca Real-time Monitoring & Debugging\n\nReplicantX provides comprehensive monitoring and debugging capabilities to help you understand what's happening during test execution.\n\n#### \ud83d\udd0d **Watch Mode (`--watch`)**\n\nReal-time conversation monitoring for observing test execution as it happens:\n\n```bash\nreplicantx run tests/agent_test.yaml --watch\n```\n\n**What you see:**\n- \ud83d\udc65 **Live conversation setup** with goal and facts\n- \ud83d\udc64 **Replicant messages** as they're sent (with timestamps)\n- \u23f1\ufe0f **Response waiting indicators**\n- \ud83e\udd16 **Agent responses** as received\n- \u2705/\u274c **Step results** with pass/fail status and timing\n- \ud83d\udcca **Final summary** with success rate, duration, goal achievement\n\n**Perfect for:**\n- \u2705 **Live demos** - Show clients real AI conversations\n- \u2705 **Test monitoring** - Watch long-running tests progress\n- \u2705 **User experience validation** - See conversation flow\n- \u2705 **Performance monitoring** - Track response times\n\n**Example Output:**\n```\n[22:04:42] \ud83d\udc65 LIVE CONVERSATION - Starting agent scenario\n[22:04:42] \ud83c\udfaf Goal: Book a business class flight to Paris\n[22:04:42] \ud83d\udc64 Replicant: Hi, I'd like to book a flight to Paris.\n[22:04:52] \u2705 Step 1: PASSED (10.2s)\n[22:04:52] \ud83e\udd16 Agent: What cabin class would you prefer?\n[22:04:53] \ud83d\udc64 Replicant: Business class, please.\n[22:05:03] \u2705 Step 2: PASSED (9.8s)\n```\n\n#### \ud83d\udd27 **Debug Mode (`--debug`)**\n\nTechnical deep-dive with detailed system information:\n\n```bash\nreplicantx run tests/agent_test.yaml --debug\n```\n\n**What you see:**\n- \ud83d\udd0d **HTTP client setup** (URL, timeout, auth provider, headers)\n- \ud83d\udd0d **Replicant agent initialization** (goal, facts, AI model settings)\n- \ud83d\udd0d **HTTP requests** (payload details, conversation history)\n- \ud83d\udd0d **API responses** (status codes, latency, content preview)\n- \ud83d\udd0d **Response validation** (assertion counts, individual results)\n- \ud83d\udd0d **AI processing** (response parsing, message generation)\n\n**Perfect for:**\n- \ud83d\udd0d **Troubleshooting** - Diagnose failed assertions\n- \ud83d\udd0d **Performance tuning** - Analyze HTTP latency and bottlenecks\n- \ud83d\udd0d **Integration debugging** - Check payload formats and API calls\n- \ud83d\udd0d **AI behavior analysis** - Understand PydanticAI decision making\n\n**Example Output:**\n```\n\ud83d\udd0d DEBUG HTTP Client initialized\n \u251c\u2500 base_url: https://api.example.com/chat\n \u251c\u2500 timeout: 120s\n \u251c\u2500 auth_provider: supabase\n \u251c\u2500 auth_headers: 2 headers\n\n\ud83d\udd0d DEBUG HTTP request payload\n \u251c\u2500 message: Hi, I'd like to book a flight to Paris.\n \u251c\u2500 conversation_history_length: 1\n \u251c\u2500 payload_size: 229 chars\n\n\ud83d\udd0d DEBUG Response validation completed\n \u251c\u2500 total_assertions: 2\n \u251c\u2500 passed_assertions: 2\n \u251c\u2500 overall_passed: True\n```\n\n#### \ud83c\udfaf **Combined Mode (`--debug --watch`)**\n\nGet both real-time conversation flow and technical details:\n\n```bash\nreplicantx run tests/agent_test.yaml --debug --watch\n```\n\n**Perfect for:**\n- \ud83c\udfaf **Development** - Full visibility during feature building\n- \ud83c\udfaf **Complex debugging** - When you need everything\n- \ud83c\udfaf **Training** - Teaching others how the system works\n- \ud83c\udfaf **Comprehensive analysis** - Complete test execution insight\n\n#### \ud83d\udca1 **Monitoring Tips**\n\n**For Long-running Tests:**\n```bash\n# Watch progress while generating a report\nreplicantx run tests/*.yaml --watch --report detailed.md\n```\n\n**For CI/CD Debugging:**\n```bash\n# Debug mode with CI exit codes\nreplicantx run tests/*.yaml --debug --ci\n```\n\n**For Performance Analysis:**\n```bash\n# Combined with verbose output\nreplicantx run tests/*.yaml --debug --verbose --report performance.json\n```\n\n### Authentication Providers\n\n#### Supabase\n```yaml\nauth:\n provider: supabase\n email: user@example.com\n password: password123\n project_url: \"{{ env.SUPABASE_URL }}\"\n api_key: \"{{ env.SUPABASE_ANON_KEY }}\"\n```\n\n#### JWT\n```yaml\nauth:\n provider: jwt\n token: \"{{ env.JWT_TOKEN }}\"\n```\n\n#### No Authentication\n```yaml\nauth:\n provider: noop\n```\n\n## \ud83e\udd16 Replicant Agent System\n\nThe Replicant agent is a Pydantic-based intelligent conversational agent that:\n\n### Key Features\n- **Fact-Based Responses**: Uses configured facts to answer API questions intelligently\n- **Natural Conversation**: Acts like a real user who doesn't provide all information upfront\n- **Customizable Behavior**: System prompts allow different personalities and response patterns\n- **Goal-Oriented**: Works toward specific objectives with completion detection\n- **Context Awareness**: Maintains conversation history and state\n\n### LLM-Powered Fact Usage\nThe agent intelligently uses configured facts through LLM integration:\n- **Context-aware**: LLMs understand when facts are relevant to questions\n- **Natural integration**: Facts are woven naturally into conversation responses \n- **Smart timing**: Agent knows when to volunteer information vs. wait to be asked\n- **Conversation memory**: Recent chat history provides context for fact usage\n\n### Conversation State Management\nReplicantX provides flexible conversation state management to handle different API architectures:\n\n#### Full Conversation History (`fullconversation: true`)\nSends the complete conversation history (including all responses) with each request:\n```yaml\nreplicant:\n fullconversation: true # Default behavior\n```\n\n**Benefits:**\n- \u2705 **Complete Context**: API receives full conversation state\n- \u2705 **Stateless APIs**: Works with APIs that don't maintain session state\n- \u2705 **Microservices**: Suitable for distributed systems\n- \u2705 **Testing Realism**: Mimics real-world stateless interactions\n\n#### Limited History (`fullconversation: false`)\nSends only the last 10 messages for performance:\n```yaml\nreplicant:\n fullconversation: false\n```\n\n**Use Cases:**\n- \ud83d\udd27 **Performance Testing**: Reduce payload size for high-volume testing\n- \ud83d\udd27 **Legacy APIs**: Compatible with APIs expecting limited context\n- \ud83d\udd27 **Memory Constraints**: When API has payload size limitations\n\n### API Payload Format Configuration\nReplicantX supports multiple API payload formats for maximum compatibility with any conversational API:\n\n#### OpenAI Format (`payload_format: openai`) - **Default**\nIndustry-standard OpenAI chat completion format:\n```yaml\nreplicant:\n payload_format: openai # Default behavior\n```\n\n**Payload Structure:**\n```json\n{\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Hello\"},\n {\"role\": \"assistant\", \"content\": \"Hi there!\"},\n {\"role\": \"user\", \"content\": \"How are you?\"}\n ]\n}\n```\n\n**Best For:**\n- \u2705 **OpenAI APIs** and compatible services\n- \u2705 **Industry standard** - widely supported\n- \u2705 **Full conversation context** with message arrays\n- \u2705 **Modern conversational AI** platforms\n\n#### Simple Format (`payload_format: simple`)\nMinimal message-only format for basic APIs:\n```yaml\nreplicant:\n payload_format: simple\n```\n\n**Payload Structure:**\n```json\n{\n \"message\": \"Hello, how are you?\"\n}\n```\n\n**Best For:**\n- \u2705 **Simple APIs** that only need the current message\n- \u2705 **Performance-critical** scenarios\n- \u2705 **Legacy systems** with minimal payload requirements\n- \u2705 **Testing basic functionality** without conversation context\n\n#### Anthropic Format (`payload_format: anthropic`)\nAnthropic Claude-compatible format:\n```yaml\nreplicant:\n payload_format: anthropic\n```\n\n**Payload Structure:**\n```json\n{\n \"messages\": [\n {\"role\": \"user\", \"content\": \"Hello\"},\n {\"role\": \"assistant\", \"content\": \"Hi there!\"}\n ]\n}\n```\n\n**Best For:**\n- \u2705 **Anthropic Claude APIs** and compatible services\n- \u2705 **Claude-based applications** and integrations\n- \u2705 **Conversational AI** platforms using Claude models\n\n#### Legacy Format (`payload_format: legacy`)\nOriginal ReplicantX format for backward compatibility:\n```yaml\nreplicant:\n payload_format: legacy\n```\n\n**Payload Structure:**\n```json\n{\n \"message\": \"Hello, how are you?\",\n \"timestamp\": \"2025-07-09T10:30:00\",\n \"conversation_history\": [\n {\"role\": \"user\", \"content\": \"Hello\"},\n {\"role\": \"assistant\", \"content\": \"Hi there!\"}\n ]\n}\n```\n\n**Best For:**\n- \ud83d\udd27 **Existing ReplicantX integrations** (backward compatibility)\n- \ud83d\udd27 **Custom APIs** expecting the original format\n- \ud83d\udd27 **Migration scenarios** when transitioning to new formats\n\n#### Session Management\n\nReplicantX supports session management to maintain conversation state across multiple API requests without sending the full conversation history each time. This is more efficient and realistic for production APIs.\n\n##### Session Modes\n\n```yaml\nreplicant:\n # Session management configuration\n session_mode: auto # disabled, auto, fixed, or env\n session_id: null # Required when session_mode is \"fixed\"\n session_timeout: 300 # Session timeout in seconds (default: 5 minutes)\n session_format: uuid # replicantx or uuid (default: uuid)\n session_placement: body # header, body, or url (default: body)\n session_variable_name: session_id # Custom name for session variable\n```\n\n**Session Modes:**\n- `disabled` (default): No session management, uses full conversation history\n- `auto`: Auto-generate unique session ID for each test run\n- `fixed`: Use a specific session ID (requires `session_id` field)\n- `env`: Use session ID from `REPLICANTX_SESSION_ID` environment variable\n\n**Session Formats:**\n- `uuid` (default): Standard UUID format (e.g., `550e8400-e29b-41d4-a716-446655440000`)\n- `replicantx`: ReplicantX format (e.g., `replicantx_c8ff856c`)\n\n**Session Placement:**\n- `body` (default): Session ID in request body/payload\n- `header`: Session ID in HTTP headers\n- `url`: Session ID in URL path (RESTful)\n\n**Session Variable Name:**\n- Custom name for the session variable in headers or body\n- Examples: `session_id`, `conversation_id`, `x-conversation-id`, `chat_id`\n\n**Session-Aware Payload Formats:**\n- `openai_session`: OpenAI-compatible with session support\n- `simple_session`: Simple format with session support\n- `restful_session`: RESTful format with session support\n\n##### Example Configurations\n\n**Auto-Generated UUID Session (Recommended):**\n```yaml\nreplicant:\n session_mode: auto\n session_format: uuid # Standard UUID format\n session_placement: body\n session_variable_name: session_id\n payload_format: openai_session\n fullconversation: false\n session_timeout: 600 # 10 minutes\n```\n\n**ReplicantX Format with Header:**\n```yaml\nreplicant:\n session_mode: auto\n session_format: replicantx # ReplicantX format\n session_placement: header\n session_variable_name: x-conversation-id\n payload_format: openai_session\n fullconversation: false\n```\n\n**Fixed Session ID with Custom Variable:**\n```yaml\nreplicant:\n session_mode: fixed\n session_id: \"test_session_12345\"\n session_format: uuid\n session_placement: body\n session_variable_name: conversation_id\n payload_format: simple_session\n fullconversation: false\n```\n\n**RESTful Session (Session ID in URL):**\n```yaml\nreplicant:\n session_mode: auto\n session_format: uuid\n session_placement: url\n payload_format: restful_session\n fullconversation: false\n# Results in requests to: /conversations/{session_id}/messages\n```\n\n**Environment-Based Session with Header:**\n```bash\n# Set environment variable\nexport REPLICANTX_SESSION_ID=\"prod_session_abc123\"\n\n# Use in YAML\nreplicant:\n session_mode: env\n session_format: uuid\n session_placement: header\n session_variable_name: x-chat-id\n payload_format: openai_session\n fullconversation: false\n```\n\n##### Session Management Benefits\n\n**\u2705 Efficiency:**\n- Reduces payload size significantly\n- Faster API requests\n- Lower bandwidth usage\n\n**\u2705 Realistic Testing:**\n- Matches production API patterns\n- Tests session handling logic\n- Validates conversation continuity\n\n**\u2705 Flexibility:**\n- Multiple session ID strategies\n- Configurable timeouts\n- Different payload formats\n\n**\u2705 Debugging:**\n- Session information in debug logs\n- Session lifecycle tracking\n- Timeout monitoring\n\n##### When to Use Session Management\n\n**Use session management when:**\n- \u2705 Your API supports conversation IDs\n- \u2705 You want to test session handling\n- \u2705 Payload size is a concern\n- \u2705 Testing production-like scenarios\n\n**Use full conversation when:**\n- \u274c API doesn't support sessions\n- \u274c Testing legacy endpoints\n- \u274c Need complete conversation context\n- \u274c Debugging conversation flow\n\n### Complete Configuration Example\n```yaml\nname: \"Universal API Test\"\nbase_url: https://api.example.com/chat\nauth:\n provider: noop\nlevel: agent\nreplicant:\n goal: \"Test API with OpenAI-compatible format\"\n facts:\n name: \"Test User\"\n email: \"test@example.com\"\n system_prompt: |\n You are a helpful user testing an API.\n initial_message: \"Hello, I'm testing the API.\"\n max_turns: 10\n completion_keywords: [\"complete\", \"finished\", \"done\"]\n fullconversation: true # Send full conversation history\n payload_format: openai # Use OpenAI-compatible format\n llm:\n model: \"test\"\n temperature: 0.7\n max_tokens: 150\n```\n\n### Session Management Examples\n\n**UUID Format with Header (Recommended for APIs):**\n```yaml\nname: \"Flight Booking with UUID Header\"\nbase_url: \"https://api.example.com/chat\"\nauth:\n provider: \"noop\"\nlevel: \"agent\"\nreplicant:\n goal: \"Book a flight from London to Paris\"\n facts:\n name: \"Alex Johnson\"\n email: \"alex@example.com\"\n departure: \"London\"\n destination: \"Paris\"\n date: \"next Friday\"\n system_prompt: \"You are a customer booking a flight. Be polite and provide details when asked.\"\n initial_message: \"Hi, I need to book a flight from London to Paris for next Friday.\"\n max_turns: 15\n session_mode: auto\n session_format: uuid # Standard UUID format\n session_placement: header # In HTTP headers\n session_variable_name: x-conversation-id # Custom header name\n payload_format: openai_session\n fullconversation: false\n session_timeout: 600\n llm:\n model: \"test\"\n```\n\n**ReplicantX Format with Body:**\n```yaml\nname: \"Customer Support with ReplicantX Body\"\nbase_url: \"https://api.example.com/support\"\nauth:\n provider: \"noop\"\nlevel: \"agent\"\nreplicant:\n goal: \"Get help with billing issue\"\n facts:\n name: \"Sarah Chen\"\n account_id: \"ACC-789456\"\n issue: \"billing\"\n system_prompt: \"You are a customer with a billing question.\"\n initial_message: \"Hello, I have a billing question.\"\n max_turns: 10\n session_mode: auto\n session_format: replicantx # ReplicantX format\n session_placement: body # In request body\n session_variable_name: conversation_id # Custom variable name\n payload_format: simple_session\n fullconversation: false\n session_timeout: 300\n llm:\n model: \"test\"\n```\n\n**UUID Format with URL (RESTful):**\n```yaml\nname: \"Pizza Order with UUID URL\"\nbase_url: \"https://api.example.com\"\nauth:\n provider: \"noop\"\nlevel: \"agent\"\nreplicant:\n goal: \"Order a pizza for delivery\"\n facts:\n name: \"Mike Rodriguez\"\n address: \"123 Main St, NYC\"\n phone: \"+1 555 123 4567\"\n system_prompt: \"You are ordering a pizza. Be friendly and provide your details.\"\n initial_message: \"Hi, I'd like to order a pizza for delivery.\"\n max_turns: 8\n session_mode: auto\n session_format: uuid # UUID format\n session_placement: url # In URL path\n payload_format: restful_session\n fullconversation: false\n # Results in requests to: /conversations/{uuid}/messages\n llm:\n model: \"test\"\n```\n\n### Migration Guide\n\n**From Legacy to OpenAI Format:**\n```yaml\n# Old configuration (still works)\nreplicant:\n payload_format: legacy # or omit entirely\n\n# New recommended configuration\nreplicant:\n payload_format: openai # More compatible with modern APIs\n```\n\n**For Simple APIs:**\n```yaml\nreplicant:\n payload_format: simple\n fullconversation: false # Not needed for simple format\n```\n\n**For Anthropic APIs:**\n```yaml\nreplicant:\n payload_format: anthropic\n fullconversation: true # Maintain conversation context\n```\n\n### System Prompt Examples\n\n**Helpful User:**\n```yaml\nsystem_prompt: |\n You are a polite user trying to achieve your goal. You have the \n necessary information but need prompting to remember details.\n```\n\n**Forgetful Customer:**\n```yaml\nsystem_prompt: |\n You are a customer who sometimes forgets details and needs \n multiple prompts. You're friendly but can be a bit scattered.\n```\n\n**Demanding User:**\n```yaml\nsystem_prompt: |\n You are an impatient user who wants quick results. You provide \n information when asked but expect efficient service.\n```\n\n## \ud83e\udde0 LLM Integration\n\nReplicantX uses **PydanticAI** for powerful LLM integration with multiple providers:\n\n### Supported Providers\n\n- **OpenAI**: GPT-4, GPT-4o, and other OpenAI models\n- **Anthropic**: Claude 4.0 Sonnet, Claude 4 Haiku, and other Claude models\n- **Google**: Gemini models via Google AI and VertexAI\n- **Groq**: Fast inference with Llama, Mixtral, and other models\n- **Ollama**: Local LLM deployment\n- **Test**: Built-in test model for development (no API keys needed)\n\n### Configuration\n\nAdd LLM configuration to your agent scenarios using PydanticAI model strings:\n\n*Technical Support Example:*\n```yaml\nlevel: agent\nreplicant:\n goal: \"Get technical support for my account\"\n facts:\n name: \"Jordan Smith\"\n # ... other facts\n system_prompt: |\n You are a customer seeking help with a technical issue.\n Use your available facts to answer questions naturally.\n # ... other config\n llm:\n model: \"openai:gpt-4.1-mini\" # PydanticAI model string\n temperature: 0.7 # Response creativity (0.0-1.0)\n max_tokens: 150 # Maximum response length\n```\n\n*Flight Booking Example:*\n```yaml\nlevel: agent\nreplicant:\n goal: \"Book a business class flight to Paris\"\n facts:\n name: \"Sarah Johnson\"\n destination: \"Paris\"\n travel_class: \"business\"\n # ... other facts\n system_prompt: |\n You are a customer trying to book a flight. You have the \n necessary information but don't provide all details upfront.\n # ... other config\n llm:\n model: \"anthropic:claude-3-5-sonnet-latest\" # PydanticAI model string\n temperature: 0.8 # Response creativity (0.0-1.0)\n max_tokens: 200 # Maximum response length\n```\n\n### Model String Examples\n\n```yaml\n# OpenAI models\nmodel: \"openai:gpt-4o\"\nmodel: \"openai:gpt-4.1-mini\"\nmodel: \"openai:gpt-4.1-nano\"\n\n# Anthropic models \nmodel: \"anthropic:claude-3-5-sonnet-latest\"\nmodel: \"anthropic:claude-3-haiku-20240307\"\n\n# Google models\nmodel: \"gemini-1.5-pro\"\nmodel: \"gemini-1.5-flash\"\n\n# Groq models\nmodel: \"groq:llama-3.1-8b-instant\"\nmodel: \"groq:mixtral-8x7b-32768\"\n\n# Test model (no API key needed)\nmodel: \"test\"\n```\n\n### Environment Variables\n\nPydanticAI automatically detects API keys from environment variables:\n\n```bash\n# OpenAI\nexport OPENAI_API_KEY=sk-your-api-key\n\n# Anthropic\nexport ANTHROPIC_API_KEY=sk-ant-your-api-key\n\n# Google AI\nexport GOOGLE_API_KEY=your-google-api-key\n\n# Groq\nexport GROQ_API_KEY=your-groq-api-key\n```\n\n### Installation with LLM Support\n\n```bash\n# Install with all LLM providers\npip install replicantx[all]\n\n# Install with specific providers\npip install replicantx[openai]\npip install replicantx[anthropic]\n\n# Core installation (includes PydanticAI with test model)\npip install replicantx\n```\n\n### How LLM Integration Works\n\n1. **Smart Prompting**: System prompts are enhanced with available facts and conversation context\n2. **Natural Responses**: LLMs generate contextually appropriate responses based on user personas\n3. **Fact Integration**: Available facts are automatically included in prompts for relevant responses\n4. **Graceful Fallback**: If LLM calls fail, the system falls back to rule-based responses\n5. **Conversation Memory**: Recent conversation history is maintained for context\n\n### Examples with PydanticAI\n\n*Customer Support Example:*\n```yaml\nname: \"Customer Support - Billing Issue\"\nbase_url: https://api.example.com/support\nauth:\n provider: noop\nlevel: agent\nreplicant:\n goal: \"Get customer support for billing issue\"\n facts:\n name: \"Alex Chen\"\n account_number: \"ACC-12345\"\n issue_type: \"billing\"\n last_payment: \"$99.99 on Jan 15th\"\n system_prompt: |\n You are a customer who is polite but slightly frustrated about \n a billing issue. You have the necessary account information but \n may need prompting to remember specific details.\n initial_message: \"Hi, I have a question about my recent bill.\"\n max_turns: 12\n completion_keywords: [\"resolved\", \"ticket created\", \"issue closed\"]\n fullconversation: true # Send full conversation history with each request\n payload_format: openai # Use OpenAI-compatible format\n llm:\n model: \"openai:gpt-4o\" # PydanticAI model string\n temperature: 0.8\n max_tokens: 120\n```\n\n*Flight Booking Example:*\n```yaml\nname: \"Travel Booking - Flight to Paris\"\nbase_url: https://api.example.com/chat\nauth:\n provider: supabase\n project_url: \"{{ env.SUPABASE_URL }}\"\n api_key: \"{{ env.SUPABASE_ANON_KEY }}\"\n email: \"{{ env.TEST_USER_EMAIL }}\"\n password: \"{{ env.TEST_USER_PASSWORD }}\"\nlevel: agent\nreplicant:\n goal: \"Book a business class flight to Paris for next weekend\"\n facts:\n name: \"Sarah Johnson\"\n email: \"sarah.johnson@example.com\"\n travel_class: \"business\"\n destination: \"Paris\"\n departure_city: \"New York\"\n travel_date: \"next Friday\"\n passengers: 1\n budget: \"$3000\"\n preferences: \"aisle seat, vegetarian meal\"\n system_prompt: |\n You are a helpful user trying to book a flight. You have all the \n necessary information but you're a typical user who doesn't \n provide all details upfront.\n initial_message: \"Hi, I'd like to book a flight to Paris for next weekend.\"\n max_turns: 15\n completion_keywords: [\"booked\", \"confirmed\", \"reservation number\", \"booking complete\"]\n fullconversation: true # Send full conversation history with each request\n payload_format: openai # Use OpenAI-compatible format\n llm:\n model: \"openai:gpt-4o\"\n temperature: 0.7\n max_tokens: 150\n```\n\n\nThese examples enable much more natural and contextually aware conversations compared to rule-based responses.\n\n## \ud83d\udd27 GitHub Actions Integration\n\nAdd this workflow to `.github/workflows/replicantx.yml`:\n\n```yaml\nname: ReplicantX E2E Tests\non:\n pull_request: { types: [opened, synchronize, reopened] }\njobs:\n replicantx:\n runs-on: ubuntu-latest\n env:\n SUPABASE_URL: ${{ secrets.SUPABASE_URL }}\n SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}\n REPLICANTX_TARGET: pr-${{ github.event.pull_request.number }}-helix-api.onrender.com\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-python@v5\n with: { python-version: \"3.11\" }\n - run: pip install \"replicantx[cli]\"\n - run: |\n until curl -sf \"https://$REPLICANTX_TARGET/health\"; do\n echo \"Waiting for preview\u2026\"; sleep 5; done\n - run: replicantx run tests/*.yaml --report report.md --ci\n - uses: marocchino/sticky-pull-request-comment@v2\n if: always()\n with: { path: report.md }\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "End-to-end testing harness for AI agents via web service API",
"version": "0.1.4",
"project_urls": {
"Documentation": "https://replicantx.org",
"Homepage": "https://github.com/helixtechnologies/replicantx",
"Issues": "https://github.com/helixtechnologies/replicantx/issues",
"Repository": "https://github.com/helixtechnologies/replicantx"
},
"split_keywords": [
"ai",
" agent",
" testing",
" e2e",
" api"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "b7b9514e2eaa6307db0133031d205587c7acd59b91c47c9c42ac5bf54405e55a",
"md5": "7a8016252c9622966f968a68ddb1f75f",
"sha256": "f1d29f8b16b5f7500622da178841906d589ab360571f93dd173f8c598876af30"
},
"downloads": -1,
"filename": "replicantx-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7a8016252c9622966f968a68ddb1f75f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 54952,
"upload_time": "2025-07-09T13:39:24",
"upload_time_iso_8601": "2025-07-09T13:39:24.802161Z",
"url": "https://files.pythonhosted.org/packages/b7/b9/514e2eaa6307db0133031d205587c7acd59b91c47c9c42ac5bf54405e55a/replicantx-0.1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e58b064b17ef9f66d7e6a0ebe01ecda9a21ba6779ad043a149bde7a7bc2d0419",
"md5": "a8e170c09467650790c9f09f228aea9b",
"sha256": "d59677eec059f9f8551b4467a2588f8f39407a1c1517919fc872dbde6d4a98d7"
},
"downloads": -1,
"filename": "replicantx-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "a8e170c09467650790c9f09f228aea9b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 63749,
"upload_time": "2025-07-09T13:39:25",
"upload_time_iso_8601": "2025-07-09T13:39:25.869690Z",
"url": "https://files.pythonhosted.org/packages/e5/8b/064b17ef9f66d7e6a0ebe01ecda9a21ba6779ad043a149bde7a7bc2d0419/replicantx-0.1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-09 13:39:25",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "helixtechnologies",
"github_project": "replicantx",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "replicantx"
}