Skip to main content

stateagent

A lightweight Python framework to structure LLM conversations using a validated state model and a tool-based interaction design.

Table of Contents

Installation

pip install stateagent

Quick Start

Here's a simple example to get you up and running:

Example Conversation

🤖 Hi! I need to collect some contact information from you.

👤 My name is John Smith

🤖 Great! I've recorded your name as John Smith.
    Now, could you please provide your email address?

👤 john@company.com

🤖 Perfect! I've saved your email.
    Finally, what message would you like to send?

👤 I'm interested in learning more about your services.

🤖 Excellent! I have all the information I need:
    ✓ Name: John Smith
    ✓ Email: john@company.com
    ✓ Message: I'm interested in learning more about your services.

    Thank you for your submission!

🏗️ Core Concepts

StateModel

Define your data structure with validation:

from dataclasses import dataclass, field
from llm_structured_agent import StateModel, Field, create_range_validator

@dataclass
class UserProfile(StateModel):
    name: str = field(default=None)
    age: int = field(default=None)
    email: str = field(default=None)

    _field_info = {
        'name': Field(
            required=True,
            description="User's full name",
            validator=create_length_validator(min_length=2)
        ),
        'age': Field(
            required=True,
            description="User's age",
            validator=create_range_validator(min_val=13, max_val=120)
        ),
        'email': Field(
            required=True,
            description="Email address",
            validator=create_email_validator()
        )
    }

CRUD Tools

The LLM automatically gets these tools to interact with state:

  • set_field(field_name, value) - Update a field with validation
  • validate_state() - Check if all required fields are complete
  • get_state() - View current state snapshot
  • clear_state() - Reset all fields to defaults

Structured Agent

The main orchestrator that manages the conversation:

agent = StructuredAgent(
    state_cls=UserProfile,
    llm=OpenAIAdapter(model="gpt-4o-mini"),
    hooks={
        "on_field_set": lambda state, field: print(f"Updated {field}"),
        "on_submit": lambda state: save_to_database(state.snapshot())
    },
    max_turns=20
)

🎨 Advanced Features

Custom Validation

import re
from llm_structured_agent import ValidationError

def validate_phone_number(value: str):
    if not re.match(r'^\+?[\d\s\-]+$', value):
        raise ValidationError("Invalid phone format")
    return value.strip()

@dataclass
class ContactInfo(StateModel):
    phone: str = field(default=None)

    _field_info = {
        'phone': Field(
            required=True,
            description="Phone number with country code",
            validator=validate_phone_number
        )
    }

Conditional Logic

@dataclass
class OrderForm(StateModel):
    item_type: str = field(default=None)
    shipping_address: str = field(default=None)
    gift_message: str = field(default=None)

    def validate(self) -> List[str]:
        missing = super().validate()

        # Gift message required for gift items
        if (self.item_type == "gift" and
            not self.gift_message):
            missing.append("gift_message")

        return missing

Lifecycle Hooks

def on_field_updated(state, field_name):
    print(f"📝 {field_name} updated to: {getattr(state, field_name)}")

def on_form_complete(state):
    # Save to database
    save_to_database(state.snapshot())

    # Send notification
    send_notification(state.email, "Form completed!")

    # Log completion
    logger.info(f"Form completed for {state.name}")

agent = StructuredAgent(
    state_cls=MyForm,
    llm=OpenAIAdapter(),
    hooks={
        "on_field_set": on_field_updated,
        "on_submit": on_form_complete
    }
)

Multiple LLM Providers

# OpenAI (default)
agent = StructuredAgent(
    state_cls=MyState,
    llm=OpenAIAdapter(model="gpt-4o-mini")
)

# Custom LLM provider
class CustomLLMAdapter(LLMAdapter):
    def chat(self, messages, tools=None):
        # Your implementation
        pass

    def extract_function_calls(self, response):
        # Your implementation
        pass

agent = StructuredAgent(
    state_cls=MyState,
    llm=CustomLLMAdapter()
)

Non-Interactive Usage

# For API endpoints or batch processing
agent = StructuredAgent(state_cls=ContactForm, llm=OpenAIAdapter())

# Process single message
result = agent.process_single_turn("My name is John and email is john@example.com")

if result["complete"]:
    print("Form completed:", result["state"])
else:
    print("Next response:", result["message"])
    print("Still missing:", result["missing_fields"])

🧪 Built-in Validators

The library includes common validators:

from llm_structured_agent import (
    create_email_validator,
    create_range_validator,
    create_length_validator,
    create_regex_validator,
    create_choice_validator
)

# Email validation
email_validator = create_email_validator()

# Numeric range
age_validator = create_range_validator(min_val=18, max_val=100)

# String length
name_validator = create_length_validator(min_length=2, max_length=50)

# Regex pattern
phone_validator = create_regex_validator(
    pattern=r'^\+?[\d\s\-]+$',
    error_message="Invalid phone number format"
)

# Choice validation
department_validator = create_choice_validator([
    "Engineering", "Sales", "Marketing", "HR"
])

📚 Examples

The library includes complete examples:

Customer Onboarding (KYC)

# Run the KYC example

python -m llm_structured_agent.examples.kyc_example

# Or if installed via pip

kyc-agent

Employee Onboarding

# Run the employee onboarding example
python -m llm_structured_agent.examples.onboarding_example

# Or if installed via pip
onboarding-agent

🔧 Configuration

Environment Variables

# Required for OpenAI

export OPENAI_API_KEY="your-openai-api-key"

# Optional: Custom model

export OPENAI_MODEL="gpt-4o-mini"

Custom System Prompts

custom_prompt = """You are a helpful assistant collecting user information.

Be conversational and friendly while systematically gathering:
- Name (required)
- Email (required)
- Phone (optional)

Use the provided tools to store information and check completeness."""

agent = StructuredAgent(
    state_cls=ContactForm,
    llm=OpenAIAdapter(),
    system_prompt=custom_prompt
)

🧪 Testing

# Install with dev dependencies

pip install stateagent[dev]

# Run tests

pytest

# Run with coverage

pytest --cov=llm_structured_agent

# Run specific test

pytest tests/test_state.py -v

📖 API Reference

StateModel

Base class for defining structured state:

class StateModel:
    def set_field(self, name: str, value: Any) -> None
    def validate(self) -> List[str]
    def snapshot(self) -> Dict[str, Any]
    def clear(self) -> None
    def get_field_info(self, name: str) -> Optional[Field]

Field

Field definition with validation:

class Field:
    def __init__(
        self,
        required: bool = False,
        description: str = "",
        validator: Optional[Callable] = None,
        default: Any = None
    )

StructuredAgent

Main orchestration class:

class StructuredAgent:
    def __init__(
        self,
        state_cls: type,
        llm: LLMAdapter,
        hooks: Optional[Dict[str, Callable]] = None,
        max_turns: int = 20,
        system_prompt: Optional[str] = None
    )

    def run_chat(self) -> None
    def process_single_turn(self, user_input: str) -> Dict[str, Any]
    def reset(self) -> None

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

📊 Roadmap

  • More LLM provider integrations
  • FastAPI integration
  • Streamlit demo interface
  • Database persistence layer
  • MCP Server

Built with ❤️ for the AI community

Metadata

Release files for stateagent 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for stateagent 0.1.0
File Size Uploaded
stateagent-0.1.0.tar.gz 20.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for stateagent 0.1.0
File Interpreter ABI Platform
stateagent-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.8 kB

Release files / stateagent-0.1.0.tar.gz

Download URL stateagent-0.1.0.tar.gz
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3f6a45b2cffacb4f1cca69a4a11f018e03974e78a3b8d21f729b9322e7085304
BLAKE2b-256 checksum
How to use checksums
0fc5fa7ddaca27983612aea29d1252e013390a707c194429903f5a4edc845c6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.18

Release files / stateagent-0.1.0-py3-none-any.whl

Download URL stateagent-0.1.0-py3-none-any.whl
Size 14.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aa19e829a747cb15ebb4edbb8099d339e37f7c944372b18beea6e0a7792a16b9
BLAKE2b-256 checksum
How to use checksums
3e6ebc61a023941c07d32d961a67bce2d83cd6b2bc5f673926d3239eaa26ea51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.10.18

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page