There are a few problems; first you need ampersand replacement, because you're calling tikzcd as part of a macro.
Second, you need to build the body of the diagram before using it.
The strategy is to split the input in a sequence, then mapping it but distinguishing between odd and even indexed entries.
\documentclass{article}
\usepackage{xparse,tikz-cd}
\ExplSyntaxOn
\NewDocumentCommand{\exactsequence}{ O{} m }
{
\perko_exactsequence:nn { #1 } { #2 }
}
\seq_new:N \l_perko_exactsequence_data_seq
\tl_new:N \l_perko_exactsequence_body_tl
\cs_new_protected:Nn \perko_exactsequence:nn
{
\seq_set_split:Nnn \l_perko_exactsequence_data_seq { ; } { #2 }
\tl_set:Nn \l_perko_exactsequence_body_tl
{
\begin{tikzcd}[ampersand~replacement=\&,#1]
}
\int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l_perko_exactsequence_data_seq }
{
\int_if_odd:nTF { ##1 }
{
\tl_put_right:Nx \l_perko_exactsequence_body_tl
{
\seq_item:Nn \l_perko_exactsequence_data_seq { ##1 }
}
}
{
\tl_put_right:Nx \l_perko_exactsequence_body_tl
{
\exp_not:N \ar [ r , "\seq_item:Nn \l_perko_exactsequence_data_seq { ##1 }" ]
\exp_not:N \&
}
}
}
\tl_put_right:Nn \l_perko_exactsequence_body_tl { \end{tikzcd} }
\tl_use:N \l_perko_exactsequence_body_tl
}
\ExplSyntaxOff
\begin{document}
\[
\exactsequence{A;a;B;b;C;c;D}
\]
\[
\exactsequence[column sep=small]{A;a;B;b;C;c;D}
\]
\end{document}
The optional argument is for options to tikzcd.
