VisionFI.Scout is a NuGet package that runs the Scout engine in your own
process — create notebooks, ingest loan documents, run recipes, read the output back —
with no server and no cloud round-trip. Install it by committing a nuget.config
that points at the VisionFI feed, then adding the package.
Three things, and only the third one needs a person.
The package targets net9.0. Older target frameworks won’t resolve it.
downloads.scoutnotebook.com
From developer machines and from CI. Restore pulls the package over plain HTTPS — no credentials, no auth header, nothing to put in a secret store.
Not needed to install — needed to run. One SyncAsync call with your
institution’s token provisions the install and pulls the recipe catalog down. Your VisionFI account
team issues it.
VisionFI.Scout is not published on nuget.org. It comes from the
VisionFI feed below. If a restore says the package can’t be found, the feed isn’t configured —
that is very nearly always the whole problem.
nuget.config
Put this file at your repository root, next to the .sln, and commit it. Every developer
who clones the repo and every CI runner that builds it then resolves the package the same way, with no
per-machine setup.
<?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <clear /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="visionfi" value="https://downloads.scoutnotebook.com/dist/scout-main/nuget/index.json" /> </packageSources> <packageSourceMapping> <packageSource key="nuget.org"> <package pattern="*" /> </packageSource> <packageSource key="visionfi"> <package pattern="VisionFI.*" /> </packageSource> </packageSourceMapping> </configuration>
Then, from the project that needs it:
It discards whatever package sources that machine has inherited — a global
NuGet.Config, a Visual Studio setting, a leftover from another project. Restore then
depends on this committed file alone, so it is deterministic instead of a function of developer-local
state.
It binds VisionFI.* to our feed and nothing else. Without it, the package ID is
resolvable from any configured source — so anyone who registers that ID on nuget.org could get
their code into a partner’s build. This is the standard dependency-confusion mitigation, and it is
the reason the mapping block is not optional.
Not this: dotnet nuget add source … writes to the developer’s
machine-level config. It’s invisible to anyone reading the repo, it doesn’t reach CI, and it
doesn’t reach the next teammate who clones. Fine for a throwaway experiment on your own box; never the
way a project is set up.
Two feeds, one package ID. Stable is what production builds against; Insiders is a nightly prerelease train for teams who want the engine as it lands.
| Channel | Cadence | Feed | How you get it |
|---|---|---|---|
| Stable | Its own cadence | /dist/scout-main/nuget/index.json | dotnet add package VisionFI.Scout |
| Insiders | Nightly, 09:00 UTC | /dist/scout-insiders/nuget/index.json | dotnet add package VisionFI.Scout --prerelease |
To use Insiders, add the second source and give it the same
VisionFI.* mapping — a pattern can map to more than one source, and NuGet will
consider both:
<packageSources> <clear /> <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="visionfi" value="https://downloads.scoutnotebook.com/dist/scout-main/nuget/index.json" /> <add key="visionfi-insiders" value="https://downloads.scoutnotebook.com/dist/scout-insiders/nuget/index.json" /> </packageSources> <packageSourceMapping> <packageSource key="nuget.org"> <package pattern="*" /> </packageSource> <packageSource key="visionfi"> <package pattern="VisionFI.*" /> </packageSource> <packageSource key="visionfi-insiders"> <package pattern="VisionFI.*" /> </packageSource> </packageSourceMapping>
With both sources configured, a plain dotnet add package still resolves Stable;
--prerelease is the opt-in. Insiders builds carry a prerelease suffix, which is what keeps
them out of the way of a normal restore.
Both feed URLs above are permanent. Partners move onto each new Stable release automatically as it publishes — nothing on their side changes, and there is no URL to update, ever.
For anything you ship, pin. Don’t use a floating range.
The package version is the version of the native engine inside it — the two are stamped together and cannot drift apart. That’s a useful property, and it’s also the reason a float is dangerous here: a floating range silently swaps the engine underneath your application, not just the managed wrapper around it.
<PackageReference Include="VisionFI.Scout" Version="x.y.z" />
Manage the version in one place with central package management: set
ManagePackageVersionsCentrally in a Directory.Packages.props at the
repo root, declare the version there once, and let each project reference the package without a version
attribute.
<Project> <PropertyGroup> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> </PropertyGroup> <ItemGroup> <PackageVersion Include="VisionFI.Scout" Version="x.y.z" /> </ItemGroup> </Project>
Upgrading is then a one-line change in one file, reviewed like any other change — which is the point.
This package is large — well over a hundred megabytes per version. That surprises people on a first restore. Nothing is wrong.
Each version carries the native Scout engine built for linux-x64,
osx-arm64 and win-x64, plus the OCR data, in the one package.
That’s the trade: a single artifact that works on every platform your team and your CI runners use,
with no per-OS install step and no OCR setup. Budget for it in CI cache sizing and on metered connections.
One line, and it belongs in your startup logs permanently.
It returns a single line in the shape
VisionFI.Scout <version> (<channel>; scout-agent <tag> @ <sha>) —
the package version, the channel it came from (stable or insiders),
and the exact engine commit bundled inside it.
The managed assembly and the native engine it binds are built from two different repositories. We hit a real
incident where the C# compiled and ran fine, no error anywhere — but the bundled engine was stale, and a
whole feature silently did nothing. Nothing in the package said which engine was inside it.
Describe() is how you find that in a minute instead of a day.
Once the package restores, the whole flow is a handful of await lines. Arguments are plain
C#; the SDK handles all marshalling into the native engine internally.
using VisionFI.Scout; // Initialize once — point at where data lives on disk. await using var scout = await ScoutKit.InitAsync(new ScoutKitConfig { ConfigDir = "/data/scout/config", // catalog + settings NotebooksDir = "/data/scout/notebooks", // the .scoutnb files }); // Provision from Scout HQ — one call, once per install (and to refresh). // Pulls the recipe catalog and everything a run needs. Just the token in. await scout.SyncAsync(hqToken); // 1. A notebook is the unit of work: one loan file or package. var meta = await scout.Notebooks.CreateAsync("United LOC"); var notebook = scout.Notebook(meta.Id); // 2. Ingest — stage every document of the package. foreach (var path in Directory.GetFiles("/loans/united-loc", "*.pdf")) await notebook.StagedFiles.StageFileAsync(path); // 3. Process — OCR + classify. This must finish before a recipe runs. await notebook.ProcessAsync(); // 4. Run a recipe (a key from Catalog.ListRecipesAsync()). var run = await notebook.Runs.RunRecipeAsync("loan-terms-summary"); // 5. Read the report back out. var reports = await notebook.Artifacts.ListByTypeAsync("loan-terms-summary"); string? report = await notebook.Artifacts.Get(reports[^1].Id).ReadTextAsync(); Console.WriteLine(report);
Open a notebook for the loan file.
Put each document in. StageFileAsync
OCR + classify. ProcessAsync
Execute the recipe. RunRecipeAsync
Pull the report. Artifacts
Ingest must finish before the recipe runs — a recipe reads the classified
documents, which only exist after processing completes. The API makes this natural: you
await each step.
Send us the output of BuildInfo.Describe() with your first message. It is the single most
useful line in any Scout SDK bug report, and it usually shortens the conversation by a day.
The feed isn’t configured for that build. Check the nuget.config is committed at
the repo root, that packageSourceMapping includes the
VisionFI.* pattern, and that the CI runner can reach
downloads.scoutnotebook.com. Remember the package is not on nuget.org.
Suspect engine skew first. Log BuildInfo.Describe() and compare the
scout-agent commit against the release you expect to be running.
Expected — see the download note above. Pin an exact version so the cache key stops moving.
hello@visionfi.ai, or your VisionFI
account team. Include Describe(), the channel you’re on, and the OS the build
runs on.