Skip to content

Diagnostics ​

The analyzer reports these errors and warnings while you type. Each one points at a mistake in your code or your build, so you fix it there instead of debugging a compiler error inside generated code.

IDSeverityTitle
TSH001ErrorToolset or agent is not partial
TSH002ErrorDeclared value is not a constant
TSH003ErrorTool is not a static method group
TSH004ErrorTool parameter cannot be bound
TSH005ErrorSettings type is not a record with a parameterless constructor
TSH006ErrorSettings are less accessible than what exposes them
TSH007ErrorTool name is not unique
TSH008ErrorTool name is not lower_snake_case
TSH009WarningTool has no description
TSH010WarningTool does not take its settings
TSH011WarningTool relies on XML docs that are not generated
TSH012ErrorConfigurable member has a type settings cannot store
TSH013ErrorConfigurable member cannot be set
TSH014ErrorDeclaration outside the constructor
TSH015ErrorChain the generator cannot read
TSH016ErrorToolset or agent is out of the generated code's reach
TSH017ErrorToolset or agent is generic or derives from another
TSH018ErrorMember clashes with a generated member
TSH019ErrorToolset was not compiled with the generator
TSH020WarningReferenced assembly was not compiled with the generator
TSH021ErrorReferenced assembly has another id type
TSH022ErrorTwo agents share a settings kind
TSH023ErrorAgent cannot be a tool or a handoff target
TSH024WarningSub-agent offers tools that need approval
TSH025ErrorTool is offered twice
TSH026ErrorAgents call each other in a circle
TSH027ErrorTool type has no JSON metadata under Native AOT
TSH028ErrorStore has another id type
TSH029ErrorId type cannot be used
TSH030ErrorProvider has another id type

Severities and suppression ​

An error fails the build. A warning lets it pass, but points at code that does not do what it seems to, such as settings that reach no parameter (TSH010). Each diagnostic's help link leads to its section on this page.

Most diagnostics are reported on the declaration they are about, so the usual suppression reaches them: #pragma warning disable TSH009 around one declaration, or a dotnet_diagnostic.TSH009.severity entry in .editorconfig. TSH020, TSH021 and TSH029 concern the whole build and have no source location, so no #pragma reaches them. To silence TSH020, the only warning of the three, add it to <NoWarn> in the project file. TSH007 and TSH022 have no location either when the clash lies between two referenced projects.

TSH001 ​

Toolset or agent is not partial. The generator adds members to every toolset and agent, so the class and every class it is nested in must be partial.

TSH002 ​

Declared value is not a constant. The generator reads WithName, WithDescription, WithStorageKind and WithSchemaVersion at compile time. Pass a literal or a const.

TSH003 ​

Tool is not a static method group. The generated function calls your tool method directly, so AddTool needs a static method that is not generic. A lambda, an instance method, a local function, a generic method or a delegate variable cannot be called that way. Pass a static method, of any accessibility: AddTool(Find).

TSH004 ​

Tool parameter cannot be bound. The model's JSON arguments cannot fill a ref or out parameter, a pointer, or a ref struct such as Span<T>.

TSH005 ​

Settings type is not a record with a parameterless constructor. That constructor sets the code defaults. Each layer of settings then changes a copy of them, made with with.

TSH006 ​

Settings are less accessible than what exposes them. Make the record, the toolset, the provider id type or the id type as accessible as what exposes it. There are four cases:

  • A settings record is less accessible than its toolset. The toolset's generated members name the record wherever the toolset can be named.
  • A toolset with configurable settings is less accessible than a public agent that offers it. The agent's Settings record names the toolset's overrides.
  • A public agent makes its model or its summary model configurable, and the provider id type is less accessible. The agent's Settings record names the type for the model's provider.
  • The build's id type is less accessible than a public agent. The agent's host members take settings ids and conversation ids of that type, so the generator keeps those members internal.

TSH007 ​

Tool name is not unique. A tool name must be unique across the toolsets of your project and of the projects it references. Names that differ only in their underscores, such as get_v2 and get_v_2, count as the same, because they map to the same generated property. Give one of the tools another name with WithName("...").

An agent's own tool needs a unique name only among the tools of the agents its standing approvals reach, and of those whose approvals reach it: the agents it hands off to, directly or through other agents, the agents that hand off to it, its sub-agents and the agents that call it as one. A standing approval names its tool, so it would reach another tool of the same name. Two agents that never share approvals may each have a tool of one name.

TSH008 ​

Tool name is not lower_snake_case. The providers' function names follow that convention, so tool names must too. With WithName, the diagnostic is on the string you passed, so change it. Otherwise the tool is named after its method, and the diagnostic is on the method in AddTool(...): rename the method, or set a name with WithName("...").

TSH009 ​

Tool has no description. The model chooses tools by their descriptions. Add a <summary> to the method, or call WithDescription.

TSH010 ​

Tool does not take its settings. The tool has WithSettings<T>() but no parameter of type T, so its settings reach nothing. Add the parameter to the method.

TSH011 ​

Tool relies on XML docs that are not generated. The compiler reads XML docs only with GenerateDocumentationFile, so set it in the project. WithDescription is a way around it only when the parameters have no <param> docs, since it replaces only the <summary>.

TSH012 ​

Configurable member has a type settings cannot store. The same error covers a Configurable(o => ...) pick of a chat option that belongs to a single run. Remove the pick, or change the member's type. A member that WithConfigurableSettings<T>() makes configurable is reported on that call, and you can leave it out with NotConfigurable(...).

  • Tool settings lists the types a configurable settings member may have.
  • Of the chat options, the model, the instructions, the sampling options, the stop sequences, multiple tool calls and reasoning may be configurable. Tools, ConversationId, ResponseFormat, ToolMode and the additional properties may not, as Builders shows.

TSH013 ​

Configurable member cannot be set. Give it a public set or init accessor.

TSH014 ​

Declaration outside the constructor. The generator reads AddTool, UseToolset and the other declarations only directly in the constructor, not in a helper method, a lambda or a local function. It also skips them under an if, in a loop or in another nested block, because there they would run only sometimes, while the generated code always includes them. Move each declaration to the top level of the constructor body.

TSH015 ​

Chain the generator cannot read. Keep each declaration one expression. The generator cannot follow a chain split over variables, such as var u = UseToolset<T>(); u.Include(...). It also reads a pick only when it names one member of the lambda's parameter, as t => t.SearchTickets in Include or s => s.Limit in Configurable do.

TSH016 ​

Toolset or agent is out of the generated code's reach. Generated code names the class and the module creates it, so it cannot be nested as private or protected, and needs a public or internal parameterless constructor.

TSH017 ​

Toolset or agent is generic or derives from another. Derive each toolset from Toolset and each agent from Agent directly, without type parameters. Share code through static methods.

TSH018 ​

Member clashes with a generated member. A member of yours has a name the generator writes, such as Settings in an agent, or CreateSearchTickets, a tool's factory, in the toolset or the agent that declares the tool. Rename your member. Generated members lists the names.

TSH019 ​

Toolset was not compiled with the generator. It is reported on UseToolset<T>(). Reference the package in the toolset's project.

TSH020 ​

Referenced assembly was not compiled with the generator. It declares toolsets or agents but carries no module of this Typeshift version, so AddTypeshift() cannot register them. Reference the package in its project, at the version the rest of the build uses.

TSH021 ​

Referenced assembly has another id type. Every project of a build shares one id type and one provider id type. Set TypeshiftIdType and TypeshiftProviderIdType once, in Directory.Build.props.

TSH022 ​

Two agents share a settings kind. Their settings would overwrite each other in the store. It happens when two agent classes have the same name in different namespaces, or when two agents set the same WithStorageKind, in one project or across a project and the projects it references. Give one of them a WithStorageKind of its own.

TSH023 ​

Agent cannot be a tool or a handoff target. The diagnostic sits on UseAgent<T>() or UseHandoff<T>() and is about the agent T. The model needs that agent's WithDescription to decide when to call it, and a lower_snake_case name to call it by: its class name in snake_case, unless WithName(...) sets another. Add a WithDescription(...) to that agent's constructor, or fix its name. An agent of a referenced project is checked too.

TSH024 ​

Sub-agent offers tools that need approval. A sub-agent cannot stop and ask your app for approval, so in Default mode its calls of such tools are rejected unless a standing approval or a rule approves them. Add an approval rule, or offer the agent with UseHandoff<T>() instead of UseAgent<T>().

TSH025 ​

Tool is offered twice. An agent offers the same tool twice when it:

  • uses the same toolset twice;
  • picks the same tool twice;
  • uses the same agent twice as a sub-agent, or twice as a handoff target;
  • uses two toolsets that each have a tool of the same name. Leave one of the two tools out, for example with Exclude(...);
  • has a tool of its own named like a tool of a toolset it uses. Rename its own tool with WithName("...").

TSH026 ​

Agents call each other in a circle. The agents offer each other as sub-agents through UseAgent<T>(), so a call could never end. Break the circle by removing one of these UseAgent<T>() calls, or by replacing one with UseHandoff<T>(), because handoffs may form circles.

TSH027 ​

Tool type has no JSON metadata under Native AOT. In a project that publishes with Native AOT or sets IsAotCompatible, the types of the parameters the model fills and the type the tool returns need source-generated metadata. List each type as [JsonSerializable(typeof(T))] on a JsonSerializerContext of the toolset's assembly (Native AOT). A context nested as private or protected does not count. These types need none: string, char, bool, short, ushort, int, uint, long, ulong, float, double, decimal, DateTime, DateTimeOffset, TimeSpan, IEnumerable<string>, JsonElement, JsonDocument and the System.Text.Json.Nodes types.

TSH028 ​

Store has another id type. WithStore<T>() takes a store of the build's id type. Implement ISettingsStore, IConversationStore or ITypeshiftStore, which is both. The generator writes these aliases for the build's id type, so they always have the right one.

TSH029 ​

Id type cannot be used. TypeshiftIdType or TypeshiftProviderIdType names a type the build does not know. Give a C# keyword (int, long, string), a type of System (Guid), or the type's full name with its namespace. A provider id is stored in the agent's Settings as one value, so TypeshiftProviderIdType also has to be a string, a number, a Guid or an enum.

TSH030 ​

Provider has another id type. WithModel(provider, model) takes a provider of the build's provider id type, and WithChatClientProvider<T>() a class that serves that type. Pass a provider of that type, or implement IChatClientProvider, the alias the generator writes for it.

  • Toolsets: the rules most toolset diagnostics guard.
  • Agents: the rules of an agent's declarations.
  • Builders: every call the analyzer checks.
  • Registration: the package, the id type and what each project needs.
  • Native AOT: the JSON metadata TSH027 asks for.

Released under the MIT License.