***

title: Soul Module
description: 'Local and remote Soul export, import, listing, and verification'
slug: ue/soul
-------------

Soul workflows in the UE plugin mirror the current core/node SDKs: local export builds an `FSoul` from store state, while remote export/import/list/verify use API-backed thunks.

## Core Types

```cpp
USTRUCT(BlueprintType)
struct FSoul {
  UPROPERTY(BlueprintReadOnly) FString Id;
  UPROPERTY(BlueprintReadOnly) FString Version;
  UPROPERTY(BlueprintReadOnly) FString Name;
  UPROPERTY(BlueprintReadOnly) FString Persona;
  UPROPERTY(BlueprintReadOnly) TArray<FMemoryItem> Memories;
  UPROPERTY(BlueprintReadOnly) FAgentState State;
  UPROPERTY(BlueprintReadOnly) FString Signature;
};

USTRUCT(BlueprintType)
struct FSoulVerifyResult {
  UPROPERTY(BlueprintReadOnly) bool bValid;
  UPROPERTY(BlueprintReadOnly) FString Reason;
};
```

`FSoulVerifyResult` is the UE-normalized verification result shape used by `verifySoulThunk(...)`.

## Local Export

Local export does not call the API. It builds an `FSoul` from the selected NPC plus the current `MemorySlice`.

```cpp
#include "RuntimeStore.h"
#include "CLI/CliOperations.h"

auto Store = createSDKStore();
FSoul LocalSoul = SDKOps::LocalExportSoul(Store, TEXT("npc_1"));
```

If no NPC id is passed, the active NPC is used.

## Remote Export

Remote export uploads a signed Soul payload through the API and Arweave flow.

```cpp
#include "RuntimeStore.h"
#include "CLI/CliOperations.h"
#include "RuntimeConfig.h"

auto Store = createSDKStore();
SDKConfig::SetApiConfig(TEXT("https://api.forboc.ai"), ApiKey);

FSoulExportResult Exported = SDKOps::ExportSoul(Store, TEXT("npc_1"));
UE_LOG(LogTemp, Display, TEXT("%s"), *Exported.TxId);
```

Remote export requires an API key.

## Import, List, And Verify

```cpp
#include "RuntimeStore.h"
#include "CLI/CliOperations.h"

auto Store = createSDKStore();
FSoul Imported = SDKOps::ImportSoul(Store, TEXT("arweave_tx_id"));
FImportedNpc ImportedNpc =
    SDKOps::ImportNpcFromSoul(Store, TEXT("arweave_tx_id"));

TArray<FSoulListItem> Souls = SDKOps::ListSouls(Store, 20);
FSoulVerifyResult Check = SDKOps::VerifySoul(Store, TEXT("arweave_tx_id"));
```

* `ImportSoul` returns a portable `FSoul`
* `ImportNpcFromSoul` also writes the imported NPC into `NPCSlice`
* `ListSouls` populates `SoulSlice::AvailableSouls`
* `VerifySoul` returns `bValid` and `Reason`

## Slice State

`SoulSlice` tracks:

* remote export status and last export
* import status and last import
* available soul list
* error state

## Direct Thunks

For direct store usage, dispatch:

* `rtk::localExportSoulThunk(NpcId)`
* `rtk::remoteExportSoulThunk(NpcId)`
* `rtk::importSoulFromArweaveThunk(TxId)`
* `rtk::importNpcFromSoulThunk(TxId)`
* `rtk::getSoulListThunk(Limit)`
* `rtk::verifySoulThunk(TxId)`
