Skip to main content

CRM Agent Environment SDK by Construct Labs - Train RL agents to interact with CRM systems

Project description

Construct Labs CRM Agent Environment

Python SDK for the Construct Labs CRM Agent Environment - a reinforcement learning environment for training AI agents to interact with CRM systems.

License

This software requires a commercial license from Construct Labs GmbH. Contact hello@construct-labs.com for licensing inquiries.

Installation

pip install construct-labs-crm-env

Quick Start

from construct_labs_crm_env import CrmAgentEnv, CrmAgentAction, CRMActionType

# Connect to the CRM environment
with CrmAgentEnv(
    base_url="https://api.construct-labs.com",
    api_key="your-api-key"  # Issued by Construct Labs
) as env:
    # Reset the environment
    result = env.reset()
    
    # List companies
    result = env.step(CrmAgentAction(
        action_type=CRMActionType.LIST_COMPANIES,
        limit=10
    ))
    print(result.observation.data)

Environment Variables

You can set your API key via environment variable:

export CRM_AGENT_API_KEY=your-api-key
# API key is read from environment
env = CrmAgentEnv(base_url="https://api.construct-labs.com")

LLM Integration Example

The SDK is designed to work with LLM-based agents. Here's how to parse LLM tool calls:

from construct_labs_crm_env import CrmAgentEnv

with CrmAgentEnv(
    base_url="https://api.construct-labs.com",
    api_key="your-api-key"
) as env:
    result = env.reset()
    
    # Simulate an LLM generating a tool call
    llm_tool_call = {
        "name": "list_companies",
        "arguments": {"limit": 5}
    }
    
    # Parse the tool call into a CrmAgentAction
    parsed = env.parse_tool_call(llm_tool_call)
    
    if parsed.is_valid:
        result = env.step(parsed.action)
        print(result.observation.model_dump_json(indent=2))
    else:
        print(f"Invalid tool call: {parsed.error_message}")

Customization

Subclass CrmAgentEnv to customize agent behavior:

Custom System Prompt

class SalesAgent(CrmAgentEnv):
    @property
    def system_prompt(self) -> str:
        return """You are a sales assistant AI.
        
Your goal is to help close deals by:
1. Finding relevant companies and contacts
2. Creating opportunities with accurate values
3. Adding follow-up tasks

Be concise. Focus on high-value opportunities."""

Restricted Tool Set

class ReadOnlyAgent(CrmAgentEnv):
    """Agent that can only read data, not modify."""
    
    @property
    def tools(self) -> list[dict]:
        read_only = {'list_companies', 'get_company', 'list_people', 
                     'get_person', 'list_opportunities', 'submit_answer'}
        return [t for t in self._default_tools() 
                if t['function']['name'] in read_only]

Custom Observation Formatting

class VerboseAgent(CrmAgentEnv):
    def format_observation(self, observation):
        base = super().format_observation(observation)
        return f"=== CRM Response ===\n{base}\n=== End ==="

Available Actions

Company Operations

  • LIST_COMPANIES - List all companies
  • GET_COMPANY - Get a specific company by ID
  • CREATE_COMPANY - Create a new company
  • UPDATE_COMPANY - Update an existing company
  • DELETE_COMPANY - Delete a company

Contact Operations

  • LIST_PEOPLE - List all contacts
  • GET_PERSON - Get a specific contact by ID
  • CREATE_PERSON - Create a new contact
  • UPDATE_PERSON - Update an existing contact
  • DELETE_PERSON - Delete a contact

Opportunity Operations

  • LIST_OPPORTUNITIES - List all opportunities
  • GET_OPPORTUNITY - Get a specific opportunity by ID
  • CREATE_OPPORTUNITY - Create a new opportunity
  • UPDATE_OPPORTUNITY - Update an existing opportunity
  • DELETE_OPPORTUNITY - Delete an opportunity

Note Operations

  • LIST_NOTES - List all notes
  • CREATE_NOTE - Create a note attached to a record

Task Operations

  • LIST_TASKS - List all tasks
  • CREATE_TASK - Create a new task
  • UPDATE_TASK - Update an existing task
  • COMPLETE_TASK - Mark a task as complete

Submit Answer

  • SUBMIT_ANSWER - Submit the final answer and end the session

Integration with Training Frameworks

Collecting Rollouts for RL Training

The SDK is designed for reinforcement learning. Here's how to collect rollouts with rewards:

from dataclasses import dataclass, field
from construct_labs_crm_env import CrmAgentEnv, CrmAgentObservation

@dataclass
class Rollout:
    """A single episode rollout for training."""
    observations: list[CrmAgentObservation] = field(default_factory=list)
    actions: list[dict] = field(default_factory=list)  # Raw tool calls
    rewards: list[float] = field(default_factory=list)
    done: bool = False
    total_reward: float = 0.0

def collect_rollout(env: CrmAgentEnv, agent, seed: int | None = None) -> Rollout:
    """Collect a single rollout from the environment."""
    rollout = Rollout()
    
    # Reset environment
    result = env.reset(seed=seed)
    rollout.observations.append(result.observation)
    
    while not result.done:
        # Get action from agent (returns tool call dict)
        tool_call = agent.get_action(
            system_prompt=env.system_prompt,
            tools=env.tools,
            observation=result.observation,
        )
        
        # Parse and execute
        parsed = env.parse_tool_call(tool_call)
        
        if parsed.is_valid:
            result = env.step(parsed.action)
            reward = result.reward if result.reward is not None else 0.0
        else:
            # Invalid action penalty
            reward = -1.0
            result.done = True
        
        # Store transition
        rollout.actions.append(tool_call)
        rollout.rewards.append(reward)
        rollout.observations.append(result.observation)
    
    rollout.done = True
    rollout.total_reward = sum(rollout.rewards)
    return rollout

# Collect multiple rollouts for training
def collect_rollouts(
    env: CrmAgentEnv,
    agent,
    num_rollouts: int,
    seed_offset: int = 0,
) -> list[Rollout]:
    """Collect multiple rollouts for batch training."""
    rollouts = []
    for i in range(num_rollouts):
        rollout = collect_rollout(env, agent, seed=seed_offset + i)
        rollouts.append(rollout)
    return rollouts

# Example usage
with CrmAgentEnv(
    base_url="https://api.construct-labs.com",
    api_key="your-api-key"
) as env:
    # Collect 10 rollouts
    rollouts = collect_rollouts(env, your_agent, num_rollouts=10)
    
    # Compute statistics
    avg_reward = sum(r.total_reward for r in rollouts) / len(rollouts)
    avg_length = sum(len(r.actions) for r in rollouts) / len(rollouts)
    
    print(f"Average reward: {avg_reward:.2f}")
    print(f"Average episode length: {avg_length:.1f}")

GRPO Training Integration

For Group Relative Policy Optimization (GRPO) training:

from construct_labs_crm_env import CrmAgentEnv

def collect_grpo_group(
    env: CrmAgentEnv,
    agent,
    group_size: int = 8,
    seed: int = 0,
) -> list[Rollout]:
    """Collect a group of rollouts with the same seed for GRPO."""
    group = []
    for _ in range(group_size):
        # Same seed = same initial state, different agent samples
        rollout = collect_rollout(env, agent, seed=seed)
        group.append(rollout)
    return group

def compute_grpo_advantages(group: list[Rollout]) -> list[float]:
    """Compute relative advantages within a group."""
    rewards = [r.total_reward for r in group]
    mean_reward = sum(rewards) / len(rewards)
    std_reward = (sum((r - mean_reward) ** 2 for r in rewards) / len(rewards)) ** 0.5
    
    if std_reward < 1e-8:
        return [0.0] * len(rewards)
    
    return [(r - mean_reward) / std_reward for r in rewards]

# Training loop
with CrmAgentEnv(
    base_url="https://api.construct-labs.com",
    api_key="your-api-key"
) as env:
    for step in range(num_training_steps):
        # Collect group of rollouts
        group = collect_grpo_group(env, agent, group_size=8, seed=step)
        
        # Compute advantages
        advantages = compute_grpo_advantages(group)
        
        # Update policy using advantages
        agent.update(group, advantages)

Basic Training Loop

from construct_labs_crm_env import CrmAgentEnv

env = CrmAgentEnv(
    base_url="https://api.construct-labs.com",
    api_key="your-api-key"
)

with env:
    result = env.reset(seed=42)
    
    while not result.done:
        # Get action from your agent/LLM
        tool_call = your_agent.get_action(
            env.system_prompt,
            env.tools,
            result.observation
        )
        
        # Parse and execute
        parsed = env.parse_tool_call(tool_call)
        if parsed.is_valid:
            result = env.step(parsed.action)
        else:
            # Handle invalid action
            print(f"Invalid action: {parsed.error_message}")
            break

API Reference

CrmAgentEnv

Main client class for interacting with the CRM environment.

Constructor:

  • base_url (str): Base URL of the CRM environment server
  • api_key (str, optional): API key for authentication
  • connect_timeout_s (float): Connection timeout in seconds (default: 10)
  • message_timeout_s (float): Message timeout in seconds (default: 60)

Methods:

  • reset(seed=None) - Reset the environment
  • step(action) - Execute an action
  • state() - Get current environment state
  • close() - Close the connection
  • parse_tool_call(tool_call) - Parse LLM tool call to action
  • format_observation(observation) - Format observation for LLM

Properties (overridable):

  • system_prompt - System prompt for the agent
  • tools - Available tool definitions

CrmAgentAction

Pydantic model for CRM actions.

action = CrmAgentAction(
    action_type=CRMActionType.CREATE_COMPANY,
    company_name="Acme Corp",
    company_domain="acme.com",
    company_employees=100
)

CrmAgentObservation

Pydantic model for CRM observations.

  • success (bool): Whether the action succeeded
  • error (str | None): Error message if failed
  • data (dict): Raw response data
  • done (bool): Whether episode has ended
  • reward (float | None): Reward signal

Use observation.model_dump_json() to get JSON representation.

Support

For licensing, technical support, or questions:

Email: hello@construct-labs.com

License

Copyright (c) 2024 Construct Labs GmbH. All rights reserved.

This software is proprietary and requires a commercial license. See LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

construct_labs_crm_env-0.1.1.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

construct_labs_crm_env-0.1.1-py3-none-any.whl (20.8 kB view details)

Uploaded Python 3

File details

Details for the file construct_labs_crm_env-0.1.1.tar.gz.

File metadata

  • Download URL: construct_labs_crm_env-0.1.1.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for construct_labs_crm_env-0.1.1.tar.gz
Algorithm Hash digest
SHA256 d1956deedbb05210b0ee88c01589adca5ebdc5900f6bcfcd3733da862033f780
MD5 c73b6af8883bce0c891b6f7c83ba11e2
BLAKE2b-256 84c68b7efb4251fb9873c3e27e35dd673b140d626f027b5ec296a0338c80df32

See more details on using hashes here.

Provenance

The following attestation bundles were made for construct_labs_crm_env-0.1.1.tar.gz:

Publisher: publish-crm-env.yml on constructlabs/mono

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file construct_labs_crm_env-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for construct_labs_crm_env-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ed9b81ac4878bf032c6308d620fea538fc956b9de782fe93a0df89c7262b11ae
MD5 c83a04056d893d14ad0c244eb8b106e7
BLAKE2b-256 b2866364bcb2dcfb9c111401200ea71d36f4ee164f07a437ce4b66c384b8bf06

See more details on using hashes here.

Provenance

The following attestation bundles were made for construct_labs_crm_env-0.1.1-py3-none-any.whl:

Publisher: publish-crm-env.yml on constructlabs/mono

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page