# How to Implement a Reward Points System for Signal Adoption in AI-Trader

> Learn how to implement a reward points system for signal adoption in AI-Trader. Integrate grant_agent_reward function into the follower copy-trade flow for efficient tracking and rewards.

- Repository: [✨Data Intelligence Lab@HKU✨/AI-Trader](https://github.com/HKUDS/AI-Trader)
- Tags: how-to-guide
- Published: 2026-05-09

---

**To implement a reward points system for signal adoption in AI-Trader, integrate the `grant_agent_reward` function from [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) into the follower copy-trade flow in [`routes_signals.py`](https://github.com/HKUDS/AI-Trader/blob/main/routes_signals.py), using `source_type='signal_adoption'` to ensure idempotent ledger entries.**

AI-Trader is an open-source trading intelligence platform that tracks agent performance through a generic reward ledger. Adding a **reward points system for signal adoption** allows leaders to earn points whenever followers copy-trade their real-time signals. This implementation leverages the existing ledger infrastructure to record adoption rewards without requiring custom SQL updates.

## Architecture of the AI-Trader Reward Ledger

The reward system centers on the `grant_agent_reward` function defined in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) (lines 18-30). This helper manages the `agent_reward_ledger` table while automatically updating the `agents.points` column, eliminating the need for manual balance adjustments.

The ledger stores reward metadata as JSON via the `_json_dumps` utility (lines 11-16), enabling flexible storage of complex adoption context. The database schema in [`service/server/database.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/database.py) (lines 670-682) defines the `agent_reward_ledger` structure with critical columns `source_type` and `source_id` that enforce idempotency.

## Detecting Signal Adoption Events

Signal adoption occurs when a follower creates a trade derived from a leader's real-time signal. In [`service/server/routes_signals.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/routes_signals.py), this happens around lines 44-55 where the system reserves a new `signal_id` for the follower, and again at lines 119-124 where the follower signal is persisted to the database. You will inject the reward logic immediately after the successful INSERT operation that creates the follower signal, ensuring the copy-trade transaction completed before granting points.

## Configuring the Adoption Reward Amount

Define a static constant to control the reward value. In [`service/server/config.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/config.py), add:

```python

# service/server/config.py

# Points awarded to signal authors when followers copy-trade

ADOPTION_REWARD = 5

```

This constant centralizes reward economics, making it easy to adjust payout rates without modifying business logic throughout the codebase.

## Granting Points on Successful Copy-Trades

After the follower signal is successfully inserted in [`routes_signals.py`](https://github.com/HKUDS/AI-Trader/blob/main/routes_signals.py) (around line 119-124), call `grant_agent_reward` to credit the original leader. The function requires `agent_id` (the leader), `amount`, `reason`, and critically `source_type` and `source_id` for deduplication.

```python

# service/server/routes_signals.py

from rewards import grant_agent_reward
from config import ADOPTION_REWARD
from experiment_events import record_reward_event

# Inside the follower-copy loop, after cursor.execute INSERT into signals

if action_lower in ['buy', 'short']:
    grant_agent_reward(
        agent_id=agent_id,                     # Leader's agent ID

        amount=ADOPTION_REWARD,
        reason='adoption_reward',
        source_type='signal_adoption',
        source_id=signal_id,                  # Original signal that was copied

        metadata={
            'adopted_by': follower_id,
            'original_signal_id': signal_id,
            'reward_type': 'adoption',
        },
    )
    
    # Optional: Emit analytics event

    record_reward_event(
        cursor,
        agent_id=agent_id,
        amount=ADOPTION_REWARD,
        reason='adoption_reward',
        source_type='signal_adoption',
        source_id=signal_id,
    )

```

## Ensuring Idempotency and Preventing Duplicates

The ledger prevents double-paying for the same adoption through the `source_type` and `source_id` composite key. In [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) (lines 47-60), `grant_agent_reward` queries existing entries with status *posted* matching these fields. If found, it returns the existing ledger ID instead of creating a duplicate row. Always use `source_type='signal_adoption'` and set `source_id` to the original leader's `signal_id` to leverage this protection.

For advanced use cases, you can also call `_add_agent_points` from [`service/server/services.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/services.py) (lines 102-113), though `grant_agent_reward` is the preferred entry point as it handles both ledger insertion and balance updates atomically.

## Optional Analytics Integration

For downstream analytics, invoke `record_reward_event` from [`service/server/experiment_events.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/experiment_events.py) (lines 70-84). This emits a structured `reward_granted` event without blocking the transaction flow, feeding data pipelines for monitoring adoption rates and reward distributions.

## Querying Adoption Rewards

Verify granted points by querying the `agent_reward_ledger` table directly:

```python
def get_adoption_rewards(agent_id: int) -> list[dict]:
    conn = get_db_connection()
    cur = conn.cursor()
    cur.execute(
        """
        SELECT *
        FROM agent_reward_ledger
        WHERE agent_id = ? AND source_type = 'signal_adoption'
        ORDER BY created_at DESC
        """,
        (agent_id,),
    )
    return [dict(r) for r in cur.fetchall()]

```

## Summary

- **`grant_agent_reward`** in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) provides the core ledger functionality for tracking adoption rewards.
- **Idempotency** is enforced via `source_type` and `source_id`, preventing duplicate payouts for the same signal adoption.
- **Configuration** is managed through constants in [`config.py`](https://github.com/HKUDS/AI-Trader/blob/main/config.py), allowing easy adjustment of reward amounts.
- **Metadata** such as `adopted_by` and `original_signal_id` is serialized via `_json_dumps` and stored in `agent_reward_ledger.metadata_json`.
- **Analytics** can be captured using `record_reward_event` from [`experiment_events.py`](https://github.com/HKUDS/AI-Trader/blob/main/experiment_events.py) for comprehensive reward tracking.

## Frequently Asked Questions

### Where is the reward ledger function defined in AI-Trader?

The `grant_agent_reward` function is defined in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) (lines 18-30). It handles inserting records into `agent_reward_ledger` and updating the `agents.points` column atomically, ensuring consistency between the ledger history and the current balance.

### How does the system prevent duplicate adoption rewards?

The system checks for existing entries with the same `source_type` and `source_id` combination in [`service/server/rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/rewards.py) (lines 47-60). If a record with status *posted* already exists, the function returns the existing ledger ID instead of creating a new entry, making the operation naturally idempotent.

### Can I modify the metadata stored with each reward?

Yes. The `metadata` parameter accepts a Python dictionary that is serialized using `_json_dumps` (lines 11-16 in [`rewards.py`](https://github.com/HKUDS/AI-Trader/blob/main/rewards.py)). You can include custom fields such as `mission_key`, follower performance metrics, or market conditions. The JSON is stored in the `metadata_json` column of `agent_reward_ledger`.

### What is the difference between `grant_agent_reward` and `_add_agent_points`?

`grant_agent_reward` is the high-level function that creates ledger entries and updates points, designed for most reward flows including adoption. `_add_agent_points` in [`service/server/services.py`](https://github.com/HKUDS/AI-Trader/blob/main/service/server/services.py) (lines 102-113) is a lower-level helper used internally for specific publishing-related rewards. For signal adoption, use `grant_agent_reward` to ensure proper ledger tracking and idempotency.