> For the complete documentation index, see [llms.txt](https://docs.powerpool.finance/powerpool-and-poweragent-network/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.powerpool.finance/powerpool-and-poweragent-network/research/poweragent-v2.1/keeper-selection.md).

# Keeper Selection

In order to introduce more advanced and optimized strategies of keeper selection, PowerAgent will be completed with different strategies of selection, the choice of which will be optional depending on the situation.

The most prioritized strategy by now is random keeper selection.

## Sources of Random Numbers

One can simply take `block.difficulty` as a source for the random number to later use it to select a keeper. However, this number does not satisfy the condition of not being deterministic.

Other, more decentralized way is to query a pseudorandom number by RanDAO. RanDAO is a blockchain based verifiable random number generator, which provides a non-deterministic pseudo random number for any contracts’ disposal.

## Keeper Assignment

In the updated contract, an `EnumerableSet.UintSet internal activeKeepers` will hold numerated keepers that are active and ready to be assigned to a Job.

A `function assignNextKeeper(bytes32 jobKey) internal` is responsible for choosing a random keeper from the set of active keepers and assigning it to the job with `jobKey`.

The main step is to randomly choose the keeper (by its index) from the set:

`index = (_getPseudoRandom() + jobKey) % NumberOfKeepers`

The function `_getPseudoRandom()` yields the pseudo random number by one of the underlying algorithms described above.

After that the keeper by the index is selected and undergoes trial for the job prerequisites.&#x20;

### Assertions

For the keeper to be successfully assigned, the following conditions must be met:

* Keeper has sufficient stake for this Job.
* Keeper must be active.

Otherwise, the `index` is increased by 1 and the next keeper from the set is checked until one satisfying the conditions is met.

### Events

On successful keeper selection, the function will `emit KeeperJobLock(nextExecutionKeeperId, jobKey)`.

The infromation on the Job's keeper that will perform the next execution and the keeper's jobs is stored in the mappings respectively:

* `mapping(bytes32 => uint256) public jobNextKeeperId`
* `mapping(uint256 => EnumerableSet.Bytes32Set) internal keeperLocksByJob`

### When Called

The assignment function is called every time a new Job is registered, a Job config is changed, a Job is topped up with credits, and, of course, after each Job execution.

## Keeper Release

The keeper is released from the job automatically after the job has been executed by this keeper, and the next keeper is assigned.

Also, a helper function `releaseKeeperIfRequired(jobKey, expectedKeeperId)` is called each time a Job owner changes the config or withdraws credits from the Job to prevent keepers from executing a task they will not receive payment for.

On special occasions the keeper can be released from the assigned job by the keeper themselves. This function may be needed when, for example, a keeper may decide to discontinue participation and withdraw their CVP stake.

The `function releaseJob(uint256 keeperId_, bytes32 jobKey_) external` is responsible for this. It can be called by the keeper admin contract.

The following requirements must be met:

* The keeper is assigned to the job specified in the arguments.
* For interval jobs, the next execution should not be awaited.
* The keeper must not undergo slashing at the time of the release.
* The job must not be resolver type.

If all met, the keeper is released from its duty.

<br>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.powerpool.finance/powerpool-and-poweragent-network/research/poweragent-v2.1/keeper-selection.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
