[Canonical page](<https://docs.dhtmlx.com/planning-engine/net/api/project-suggest-assignments/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# Project.SuggestAssignments

Proposes resources for the requirement slots of a [`Project`](<https://docs.dhtmlx.com/planning-engine/net/api/core/project/project.md>). It fills empty slots, repairs broken ones and rebalances valid ones, and scores each step the way [`Evaluate`](<https://docs.dhtmlx.com/planning-engine/net/api/project-evaluate.md>) does. The project isn't modified; the proposal comes back as a change set. Needs a solved project with no unsolved edits.

## Signature

```csharp
public SuggestResult SuggestAssignments(IReadOnlyList<Slot> slots, SuggestOptions options)
```

Synchronous and CPU-only. Doesn't change the project's state.

## Parameters

| Name | Type | Description |
|---|---|---|
| `slots` | `IReadOnlyList<`[`Slot`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>)`>` | The slots to fill or rebalance. To build them from skills and requirements, use [`SkillLayer.Slots`](<https://docs.dhtmlx.com/planning-engine/net/api/skill-layer-slots.md>). To build your own, read the current state with [`Roster`](<https://docs.dhtmlx.com/planning-engine/net/api/project-roster.md>). |
| `options` | [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-options.md>) | Expected baseline, targets, fixed assignments, penalty, passes, leveling stage and `ClearFirst` |

## Behavior

- Greedy: it visits slots one at a time, and later slots build on earlier picks.
- It never removes an assignment. It adds one per filled slot and changes the resource of a repaired or rebalanced one.
- With `options.ClearFirst`, the proposal also carries the leveling clears it measured against. See [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-options.md>).
- Commit the proposal with [`Apply(result.Changes)`](<https://docs.dhtmlx.com/planning-engine/net/api/project-apply.md>), then [`Solve(null, …)`](<https://docs.dhtmlx.com/planning-engine/net/api/project-solve.md>). When `options.Level` was set, call [`Level`](<https://docs.dhtmlx.com/planning-engine/net/api/project-level.md>) with the same leveling options instead.

## Returns

A [`SuggestResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-result.md>) with the proposed changes and a step log.

## Errors

| Error | When |
|---|---|
| [`ProjectException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/project-exception.md>) `NoBaseline` | The project is unsolved, including after `Apply` |
| `ProjectException` `StaleBaseline` | `options.BaselineId` doesn't name the current baseline |
| [`InputException`](<https://docs.dhtmlx.com/planning-engine/net/api/core/errors/input-exception.md>) | Invalid options (`newResourcePenalty`, `passes`, `targets[i]`, `fixed[i]`, `Level`); a cyclic accepted state (`Path` is `null`); an invalid slot (paths under `slots[i]`) |
| `ArgumentNullException` | `slots` or `options` is `null` |

It checks options before slots. The accepted values are on the [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-options.md>) and [`Slot`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>) pages.

## Example

Fill an open position on task `C`, then commit the proposal.

```csharp
using Plen;

var start = Moment.FromYmdHm(2026, 8, 10, 0, 0) ?? throw new InvalidOperationException("invalid date");
var data = new ProjectData
{
    Tasks =
    [
        new TaskData("A") { StartDate = start, Duration = 2.0 },
        new TaskData("C") { StartDate = start, Duration = 2.0 },
    ],
    Resources = [new ResourceData { Id = "dev1" }, new ResourceData { Id = "dev2" }],
    Assignments = [new AssignmentData { Id = "aA", Task = "A", Resource = "dev1", Value = 1.0 }],
};
data.Config.UseCalendars = false;

var project = new Project();
project.Solve(data, new SolveOptions());

// Task C needs one person: dev1 or dev2.
List<Slot> slots = [new Slot("sC", "C", ["dev1", "dev2"])];
var result = project.SuggestAssignments(slots, new SuggestOptions());
foreach (var step in result.Steps)
    Console.WriteLine($"{step.Slot} -> {step.ToResource}"); // sC -> dev2

var report = project.Apply(result.Changes);
if (report.Rejected.Count == 0)
    project.Solve(null, new SolveOptions());
```

## Related

- [`Slot`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/slot.md>) - the slots to fill
- [`SuggestOptions`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-options.md>) - the options
- [`SuggestResult`](<https://docs.dhtmlx.com/planning-engine/net/api/core/suggest/suggest-result.md>) - the returned proposal
- [Suggesting assignments](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/suggesting-assignments.md>) - how picks are made and how to read the proposal
- [Skills and requirements](<https://docs.dhtmlx.com/planning-engine/net/resources-and-assignment/skills-and-requirements.md>) - slots from workers and requirements
